Merge lp:~stub/launchpad/pending-db-changes into lp:launchpad/db-devel

Proposed by Stuart Bishop
Status: Merged
Approved by: Michael Hudson-Doyle
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~stub/launchpad/pending-db-changes
Merge into: lp:launchpad/db-devel
Diff against target: 1738 lines (+111/-1347)
10 files modified
database/replication/Makefile (+15/-36)
database/replication/authdb_create.sql (+0/-885)
database/replication/authdb_drop.sql (+0/-14)
database/replication/authdb_sequences.sql (+0/-22)
database/replication/helpers.py (+12/-30)
database/replication/initialize.py (+6/-53)
database/replication/new-slave.py (+36/-42)
database/replication/populate_auth_replication_set.py (+0/-177)
database/schema/security.cfg (+9/-55)
database/schema/trusted.sql (+33/-33)
To merge this branch: bzr merge lp:~stub/launchpad/pending-db-changes
Reviewer Review Type Date Requested Status
Michael Hudson-Doyle Approve
Review via email: mp+23116@code.launchpad.net

Commit message

The authdb replication set has been collapsed into the lpmain replication set on production, so make the staging environment match. Also, fix new-slave.py.

Description of the change

This branch refactors the staging setup to match our new, simpler production environment. The authdb replication set is now gone. We also do some related cleanups, such as fixing the synchronization bug in new-slave.py so it should stop failing on production.

Some tidying was done to trusted.sql, making some lines wrap at 80 columns. Also some obsolete permissions where stripped from security.cfg.

To post a comment you must log in.
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

This all looks good to me, although there's obviously quite a bit of trust involved in me saying that.

I noticed a typo in a comment near one of your changes:

# Turn off silencing for now so we details on staging deployments.

Please fix that and land!

review: Approve
Revision history for this message
Stuart Bishop (stub) wrote :

Live in Thailand long time now. Speak only en_TH. Fix comment now en_US already.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'database/replication/Makefile'
2--- database/replication/Makefile 2010-03-26 08:43:39 +0000
3+++ database/replication/Makefile 2010-04-13 06:35:59 +0000
4@@ -44,14 +44,16 @@
5
6 PGMASSACRE=../../utilities/pgmassacre.py
7
8-# Turn off silencing for now so we details on staging deployments.
9+CREATEDB_83=createdb --encoding=UTF8
10+CREATEDB_84=createdb --encoding=UTF8 --locale=C --template=template0
11+CREATEDB=${CREATEDB_83}
12+
13+# Turn off output silencing so we can see details of staging deployments.
14+# Without the timestamps, we are unable to estimate production deployment
15+# times.
16 #SHHH=../../utilities/shhh.py
17 SHHH=
18
19-AUTHDB_TABLES=\
20- account accountpassword authkoken emailaddress \
21- openidassociation openidauthorization openidnonce openidrpsummary
22-
23 default:
24 echo Usage: make [start|stop|restart]
25
26@@ -76,7 +78,7 @@
27
28 # Replicate it again, so we can test with multiple slaves.
29 -${PGMASSACRE} launchpad_dev_slave2
30- createdb --encoding=UTF8 launchpad_dev_slave2
31+ ${CREATEDB} launchpad_dev_slave2
32 LPCONFIG=${DEV_CONFIG} ./slon_ctl.py start \
33 node3_node 'dbname=launchpad_dev_slave2 user=slony'
34 LPCONFIG=${DEV_CONFIG} ./new-slave.py 3 launchpad_dev_slave2
35@@ -96,23 +98,12 @@
36 _MASTER=lpmain_staging_new _SLAVE=lpmain_staging_slave_new \
37 LAG="0 seconds"
38 # Create the DB with the desired default tablespace.
39- createdb --encoding UTF8 --tablespace ${STAGING_TABLESPACE} \
40- lpmain_staging_new
41- # Restore the DB schema. We need to restore permissions, despite
42+ ${CREATEDB} --tablespace ${STAGING_TABLESPACE} lpmain_staging_new
43+ # Restore the database. We need to restore permissions, despite
44 # later running security.py, to pull in permissions granted on
45 # production to users not maintained by security.py.
46 pg_restore --dbname=lpmain_staging_new \
47 --no-owner --exit-on-error ${STAGING_DUMP}
48- psql -q -d lpmain_staging_new -f authdb_drop.sql
49- psql -q -d lpmain_staging_new -f authdb_create.sql \
50- 2>&1 | grep -v _sl || true
51- # Restore the authdb data.
52- for table in ${AUTHDB_TABLES}; do \
53- pg_restore --dbname=lpmain_staging_new \
54- --no-acl --no-owner --disable-triggers --data-only \
55- --table=$$table ${STAGING_DUMP}; \
56- done
57- psql -q -d lpmain_staging_new -f authdb_sequences.sql
58 # Uninstall Slony-I if it is installed - a pg_dump of a DB with
59 # Slony-I installed isn't usable without this step.
60 LPCONFIG=${NEW_STAGING_CONFIG} ./repair-restored-db.py
61@@ -144,17 +135,9 @@
62 LPCONFIG=${STAGING_CONFIG} ./slon_ctl.py --lag="${LAG}" start
63
64 dogfood:
65- createdb --encoding UTF8 ${DOGFOOD_DBNAME}
66+ ${CREATEDB} ${DOGFOOD_DBNAME}
67 pg_restore --dbname=${DOGFOOD_DBNAME} --no-acl --no-owner \
68 --exit-on-error ${DOGFOOD_DUMP}
69- psql -q -d ${DOGFOOD_DBNAME} -f authdb_drop.sql
70- psql -q -d ${DOGFOOD_DBNAME} -f authdb_create.sql \
71- 2>&1 | grep -v _sl || true
72- for table in ${AUTHDB_TABLES}; do \
73- pg_restore --dbname=${DOGFOOD_DBNAME} \
74- --no-acl --no-owner --disable-triggers --data-only \
75- --table=$$table ${DOGFOOD_DUMP}; \
76- done
77 ./repair-restored-db.py -d ${DOGFOOD_DBNAME}
78 ../schema/upgrade.py -d ${DOGFOOD_DBNAME}
79 ../schema/fti.py -d ${DOGFOOD_DBNAME}
80@@ -174,14 +157,15 @@
81 _replicate:
82 @echo LPCONFIG currently ${LPCONFIG}
83 # Start the slon daemon for the master.
84- ./slon_ctl.py start \
85+ ./slon_ctl.py --lag="0 seconds" start \
86 node1_node "dbname=${_MASTER} user=slony"
87 # Initialize the cluster and create replication sets.
88 ./initialize.py
89 # Create the soon-to-be-slave database, empty at this point.
90- createdb --encoding=UTF8 --tablespace=${_SLAVE_TABLESPACE} ${_SLAVE}
91+ ${CREATEDB} --tablespace=${_SLAVE_TABLESPACE} ${_SLAVE}
92 # Start the slon daemon for the slave
93- ./slon_ctl.py start node2_node "dbname=${_SLAVE} user=slony"
94+ ./slon_ctl.py --lag="0 seconds" start \
95+ node2_node "dbname=${_SLAVE} user=slony"
96 # Setup the slave
97 ./new-slave.py 2 "dbname=${_SLAVE}"
98 # Upgrade all databases in the cluster and reset security.
99@@ -192,12 +176,7 @@
100 @echo Running security.py `date`
101 ./slon_ctl.py stop # security.py can deadlock with slony
102 ${SHHH} ../schema/security.py --cluster -U slony
103- ./slon_ctl.py --lag="0 seconds" start
104- # Migrate tables to the authdb replication set, creating the set
105- # and subscribing nodes to it as necessary.
106- ./populate_auth_replication_set.py -U slony
107 # Restart slon daemons with default lag setting.
108- ./slon_ctl.py stop
109 ./slon_ctl.py --lag="${LAG}" start
110 # Generate a preamble for manual slonik(1) usage.
111 ./preamble.py > preamble.sk
112
113=== removed file 'database/replication/authdb_create.sql'
114--- database/replication/authdb_create.sql 2010-03-30 05:51:30 +0000
115+++ database/replication/authdb_create.sql 1970-01-01 00:00:00 +0000
116@@ -1,885 +0,0 @@
117--- Copyright 2009 Canonical Ltd. This software is licensed under the
118--- GNU Affero General Public License version 3 (see the file LICENSE).
119-
120--- Generated by:
121--- pg_dump --format=p --schema-only --no-owner --no-privileges \
122--- --table=Account --table=AccountPassword --table=AuthToken \
123--- --table=EmailAddress --table=OpenIDAssociation \
124--- --table=OpenIDAuthorization --table=OpenIDNonce \
125--- --table=OpenIDRPSummary --table=ValidPersonCache \
126--- --table=ValidPersonOrTeamCache launchpad_prod_4
127-
128---
129--- PostgreSQL database dump
130---
131-
132-SET client_encoding = 'UTF8';
133-SET standard_conforming_strings = off;
134-SET check_function_bodies = false;
135-SET client_min_messages = warning;
136-SET escape_string_warning = off;
137-
138-SET search_path = public, pg_catalog;
139-
140-SET default_tablespace = '';
141-
142-SET default_with_oids = false;
143-
144---
145--- Name: account; Type: TABLE; Schema: public; Owner: -; Tablespace:
146---
147-
148-CREATE TABLE account (
149- id integer NOT NULL,
150- date_created timestamp without time zone DEFAULT timezone('UTC'::text, now()) NOT NULL,
151- creation_rationale integer NOT NULL,
152- status integer NOT NULL,
153- date_status_set timestamp without time zone DEFAULT timezone('UTC'::text, now()) NOT NULL,
154- displayname text NOT NULL,
155- openid_identifier text DEFAULT generate_openid_identifier() NOT NULL,
156- status_comment text,
157- old_openid_identifier text
158-);
159-
160-
161---
162--- Name: TABLE account; Type: COMMENT; Schema: public; Owner: -
163---
164-
165-COMMENT ON TABLE account IS 'An account that may be used for authenticating to Canonical or other systems.';
166-
167-
168---
169--- Name: COLUMN account.status; Type: COMMENT; Schema: public; Owner: -
170---
171-
172-COMMENT ON COLUMN account.status IS 'The status of the account.';
173-
174-
175---
176--- Name: COLUMN account.date_status_set; Type: COMMENT; Schema: public; Owner: -
177---
178-
179-COMMENT ON COLUMN account.date_status_set IS 'When the status was last changed.';
180-
181-
182---
183--- Name: COLUMN account.displayname; Type: COMMENT; Schema: public; Owner: -
184---
185-
186-COMMENT ON COLUMN account.displayname IS 'Name to display when rendering information about this account.';
187-
188-
189---
190--- Name: COLUMN account.openid_identifier; Type: COMMENT; Schema: public; Owner: -
191---
192-
193-COMMENT ON COLUMN account.openid_identifier IS 'The key used to construct an OpenID identity URL for this account.';
194-
195-
196---
197--- Name: COLUMN account.status_comment; Type: COMMENT; Schema: public; Owner: -
198---
199-
200-COMMENT ON COLUMN account.status_comment IS 'The comment on the status of the account.';
201-
202-
203---
204--- Name: COLUMN account.old_openid_identifier; Type: COMMENT; Schema: public; Owner: -
205---
206-
207-COMMENT ON COLUMN account.old_openid_identifier IS 'The previous openid_identifier, used for transitions to the current openid_identifier.';
208-
209-
210---
211--- Name: account_id_seq; Type: SEQUENCE; Schema: public; Owner: -
212---
213-
214-CREATE SEQUENCE account_id_seq
215- INCREMENT BY 1
216- NO MAXVALUE
217- NO MINVALUE
218- CACHE 1;
219-
220-
221---
222--- Name: account_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
223---
224-
225-ALTER SEQUENCE account_id_seq OWNED BY account.id;
226-
227-
228---
229--- Name: accountpassword; Type: TABLE; Schema: public; Owner: -; Tablespace:
230---
231-
232-CREATE TABLE accountpassword (
233- id integer NOT NULL,
234- account integer NOT NULL,
235- password text NOT NULL
236-);
237-
238-
239---
240--- Name: TABLE accountpassword; Type: COMMENT; Schema: public; Owner: -
241---
242-
243-COMMENT ON TABLE accountpassword IS 'A password used to authenticate an Account.';
244-
245-
246---
247--- Name: COLUMN accountpassword.password; Type: COMMENT; Schema: public; Owner: -
248---
249-
250-COMMENT ON COLUMN accountpassword.password IS 'SSHA digest encrypted password.';
251-
252-
253---
254--- Name: accountpassword_id_seq; Type: SEQUENCE; Schema: public; Owner: -
255---
256-
257-CREATE SEQUENCE accountpassword_id_seq
258- INCREMENT BY 1
259- NO MAXVALUE
260- NO MINVALUE
261- CACHE 1;
262-
263-
264---
265--- Name: accountpassword_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
266---
267-
268-ALTER SEQUENCE accountpassword_id_seq OWNED BY accountpassword.id;
269-
270-
271---
272--- Name: authtoken; Type: TABLE; Schema: public; Owner: -; Tablespace:
273---
274-
275-CREATE TABLE authtoken (
276- id integer NOT NULL,
277- date_created timestamp without time zone DEFAULT timezone('UTC'::text, now()) NOT NULL,
278- date_consumed timestamp without time zone,
279- token_type integer NOT NULL,
280- token text NOT NULL,
281- requester integer,
282- requester_email text,
283- email text NOT NULL,
284- redirection_url text
285-);
286-
287-
288---
289--- Name: TABLE authtoken; Type: COMMENT; Schema: public; Owner: -
290---
291-
292-COMMENT ON TABLE authtoken IS 'AuthToken stores one time tokens used by the authentication service for validating email addresses and other tasks that require verifying an email address is valid such as password recovery and account merging. This table will be cleaned occasionally to remove expired tokens. Expiry time is not yet defined.';
293-
294-
295---
296--- Name: COLUMN authtoken.date_created; Type: COMMENT; Schema: public; Owner: -
297---
298-
299-COMMENT ON COLUMN authtoken.date_created IS 'The timestamp that this request was made.';
300-
301-
302---
303--- Name: COLUMN authtoken.date_consumed; Type: COMMENT; Schema: public; Owner: -
304---
305-
306-COMMENT ON COLUMN authtoken.date_consumed IS 'The date and time when this token was consumed. It''s NULL if it hasn''t been consumed yet.';
307-
308-
309---
310--- Name: COLUMN authtoken.token_type; Type: COMMENT; Schema: public; Owner: -
311---
312-
313-COMMENT ON COLUMN authtoken.token_type IS 'The type of request, as per dbschema.TokenType.';
314-
315-
316---
317--- Name: COLUMN authtoken.token; Type: COMMENT; Schema: public; Owner: -
318---
319-
320-COMMENT ON COLUMN authtoken.token IS 'The token (not the URL) emailed used to uniquely identify this request. This token will be used to generate a URL that when clicked on will continue a workflow.';
321-
322-
323---
324--- Name: COLUMN authtoken.requester; Type: COMMENT; Schema: public; Owner: -
325---
326-
327-COMMENT ON COLUMN authtoken.requester IS 'The Account that made this request. This will be null for password recovery requests.';
328-
329-
330---
331--- Name: COLUMN authtoken.requester_email; Type: COMMENT; Schema: public; Owner: -
332---
333-
334-COMMENT ON COLUMN authtoken.requester_email IS 'The email address that was used to login when making this request. This provides an audit trail to help the end user confirm that this is a valid request. It is not a link to the EmailAddress table as this may be changed after the request is made. This field will be null for password recovery requests.';
335-
336-
337---
338--- Name: COLUMN authtoken.email; Type: COMMENT; Schema: public; Owner: -
339---
340-
341-COMMENT ON COLUMN authtoken.email IS 'The email address that this request was sent to.';
342-
343-
344---
345--- Name: authtoken_id_seq; Type: SEQUENCE; Schema: public; Owner: -
346---
347-
348-CREATE SEQUENCE authtoken_id_seq
349- INCREMENT BY 1
350- NO MAXVALUE
351- NO MINVALUE
352- CACHE 1;
353-
354-
355---
356--- Name: authtoken_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
357---
358-
359-ALTER SEQUENCE authtoken_id_seq OWNED BY authtoken.id;
360-
361-
362---
363--- Name: emailaddress; Type: TABLE; Schema: public; Owner: -; Tablespace:
364---
365-
366-CREATE TABLE emailaddress (
367- id integer NOT NULL,
368- email text NOT NULL,
369- person integer,
370- status integer NOT NULL,
371- date_created timestamp without time zone DEFAULT timezone('UTC'::text, now()) NOT NULL,
372- account integer,
373- CONSTRAINT emailaddress__is_linked__chk CHECK (((person IS NOT NULL) OR (account IS NOT NULL)))
374-);
375-
376-
377---
378--- Name: COLUMN emailaddress.email; Type: COMMENT; Schema: public; Owner: -
379---
380-
381-COMMENT ON COLUMN emailaddress.email IS 'An email address used by a Person. The email address is stored in a casesensitive way, but must be case insensitivly unique.';
382-
383-
384---
385--- Name: emailaddress_id_seq; Type: SEQUENCE; Schema: public; Owner: -
386---
387-
388-CREATE SEQUENCE emailaddress_id_seq
389- INCREMENT BY 1
390- NO MAXVALUE
391- NO MINVALUE
392- CACHE 1;
393-
394-
395---
396--- Name: emailaddress_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
397---
398-
399-ALTER SEQUENCE emailaddress_id_seq OWNED BY emailaddress.id;
400-
401-
402---
403--- Name: openidassociation; Type: TABLE; Schema: public; Owner: -; Tablespace:
404---
405-
406-CREATE TABLE openidassociation (
407- server_url character varying(2047) NOT NULL,
408- handle character varying(255) NOT NULL,
409- secret bytea,
410- issued integer,
411- lifetime integer,
412- assoc_type character varying(64),
413- CONSTRAINT secret_length_constraint CHECK ((length(secret) <= 128))
414-);
415-
416-
417---
418--- Name: openidauthorization; Type: TABLE; Schema: public; Owner: -; Tablespace:
419---
420-
421-CREATE TABLE openidauthorization (
422- id integer NOT NULL,
423- account integer NOT NULL,
424- client_id text,
425- date_created timestamp without time zone DEFAULT timezone('UTC'::text, now()) NOT NULL,
426- date_expires timestamp without time zone NOT NULL,
427- trust_root text NOT NULL
428-);
429-
430-
431---
432--- Name: openidauthorization_id_seq; Type: SEQUENCE; Schema: public; Owner: -
433---
434-
435-CREATE SEQUENCE openidauthorization_id_seq
436- INCREMENT BY 1
437- NO MAXVALUE
438- NO MINVALUE
439- CACHE 1;
440-
441-
442---
443--- Name: openidauthorization_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
444---
445-
446-ALTER SEQUENCE openidauthorization_id_seq OWNED BY openidauthorization.id;
447-
448-
449---
450--- Name: openidnonce; Type: TABLE; Schema: public; Owner: -; Tablespace:
451---
452-
453-CREATE TABLE openidnonce (
454- server_url character varying(2047) NOT NULL,
455- "timestamp" integer NOT NULL,
456- salt character(40) NOT NULL
457-);
458-
459-
460---
461--- Name: TABLE openidnonce; Type: COMMENT; Schema: public; Owner: -
462---
463-
464-COMMENT ON TABLE openidnonce IS 'Nonces for our OpenID consumer.';
465-
466-
467---
468--- Name: openidrpsummary; Type: TABLE; Schema: public; Owner: -; Tablespace:
469---
470-
471-CREATE TABLE openidrpsummary (
472- id integer NOT NULL,
473- account integer NOT NULL,
474- openid_identifier text NOT NULL,
475- trust_root text NOT NULL,
476- date_created timestamp without time zone DEFAULT timezone('UTC'::text, now()) NOT NULL,
477- date_last_used timestamp without time zone DEFAULT timezone('UTC'::text, now()) NOT NULL,
478- total_logins integer DEFAULT 1 NOT NULL
479-);
480-
481-
482---
483--- Name: TABLE openidrpsummary; Type: COMMENT; Schema: public; Owner: -
484---
485-
486-COMMENT ON TABLE openidrpsummary IS 'The summary of the activity between a person and an RP.';
487-
488-
489---
490--- Name: COLUMN openidrpsummary.account; Type: COMMENT; Schema: public; Owner: -
491---
492-
493-COMMENT ON COLUMN openidrpsummary.account IS 'The account who used the RP.';
494-
495-
496---
497--- Name: COLUMN openidrpsummary.openid_identifier; Type: COMMENT; Schema: public; Owner: -
498---
499-
500-COMMENT ON COLUMN openidrpsummary.openid_identifier IS 'The OpenID identifier used to login.';
501-
502-
503---
504--- Name: COLUMN openidrpsummary.trust_root; Type: COMMENT; Schema: public; Owner: -
505---
506-
507-COMMENT ON COLUMN openidrpsummary.trust_root IS 'The trust root for the RP';
508-
509-
510---
511--- Name: COLUMN openidrpsummary.date_created; Type: COMMENT; Schema: public; Owner: -
512---
513-
514-COMMENT ON COLUMN openidrpsummary.date_created IS 'The creation date of this summary; the first time the person used the RP.';
515-
516-
517---
518--- Name: COLUMN openidrpsummary.date_last_used; Type: COMMENT; Schema: public; Owner: -
519---
520-
521-COMMENT ON COLUMN openidrpsummary.date_last_used IS 'The date the RP was last used.';
522-
523-
524---
525--- Name: COLUMN openidrpsummary.total_logins; Type: COMMENT; Schema: public; Owner: -
526---
527-
528-COMMENT ON COLUMN openidrpsummary.total_logins IS 'The total number of times the RP was used by the person.';
529-
530-
531---
532--- Name: openidrpsummary_id_seq; Type: SEQUENCE; Schema: public; Owner: -
533---
534-
535-CREATE SEQUENCE openidrpsummary_id_seq
536- INCREMENT BY 1
537- NO MAXVALUE
538- NO MINVALUE
539- CACHE 1;
540-
541-
542---
543--- Name: openidrpsummary_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
544---
545-
546-ALTER SEQUENCE openidrpsummary_id_seq OWNED BY openidrpsummary.id;
547-
548-
549---
550--- Name: validpersoncache; Type: VIEW; Schema: public; Owner: -
551---
552-
553-CREATE VIEW validpersoncache AS
554- SELECT emailaddress.person AS id FROM emailaddress, account WHERE ((((emailaddress.account = account.id) AND (emailaddress.person IS NOT NULL)) AND (emailaddress.status = 4)) AND (account.status = 20));
555-
556-
557---
558--- Name: VIEW validpersoncache; Type: COMMENT; Schema: public; Owner: -
559---
560-
561-COMMENT ON VIEW validpersoncache IS 'A materialized view listing the Person.ids of all valid people (but not teams).';
562-
563-
564---
565--- Name: validpersonorteamcache; Type: VIEW; Schema: public; Owner: -
566---
567-
568-CREATE VIEW validpersonorteamcache AS
569- SELECT person.id FROM ((person LEFT JOIN emailaddress ON ((person.id = emailaddress.person))) LEFT JOIN account ON ((emailaddress.account = account.id))) WHERE ((person.teamowner IS NOT NULL) OR ((account.status = 20) AND (emailaddress.status = 4)));
570-
571-
572---
573--- Name: id; Type: DEFAULT; Schema: public; Owner: -
574---
575-
576-ALTER TABLE account ALTER COLUMN id SET DEFAULT nextval('account_id_seq'::regclass);
577-
578-
579---
580--- Name: id; Type: DEFAULT; Schema: public; Owner: -
581---
582-
583-ALTER TABLE accountpassword ALTER COLUMN id SET DEFAULT nextval('accountpassword_id_seq'::regclass);
584-
585-
586---
587--- Name: id; Type: DEFAULT; Schema: public; Owner: -
588---
589-
590-ALTER TABLE authtoken ALTER COLUMN id SET DEFAULT nextval('authtoken_id_seq'::regclass);
591-
592-
593---
594--- Name: id; Type: DEFAULT; Schema: public; Owner: -
595---
596-
597-ALTER TABLE emailaddress ALTER COLUMN id SET DEFAULT nextval('emailaddress_id_seq'::regclass);
598-
599-
600---
601--- Name: id; Type: DEFAULT; Schema: public; Owner: -
602---
603-
604-ALTER TABLE openidauthorization ALTER COLUMN id SET DEFAULT nextval('openidauthorization_id_seq'::regclass);
605-
606-
607---
608--- Name: id; Type: DEFAULT; Schema: public; Owner: -
609---
610-
611-ALTER TABLE openidrpsummary ALTER COLUMN id SET DEFAULT nextval('openidrpsummary_id_seq'::regclass);
612-
613-
614---
615--- Name: account_openid_identifier_key; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
616---
617-
618-ALTER TABLE ONLY account
619- ADD CONSTRAINT account_openid_identifier_key UNIQUE (openid_identifier);
620-
621-
622---
623--- Name: account_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
624---
625-
626-ALTER TABLE ONLY account
627- ADD CONSTRAINT account_pkey PRIMARY KEY (id);
628-
629-
630---
631--- Name: accountpassword_account_key; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
632---
633-
634-ALTER TABLE ONLY accountpassword
635- ADD CONSTRAINT accountpassword_account_key UNIQUE (account);
636-
637-
638---
639--- Name: accountpassword_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
640---
641-
642-ALTER TABLE ONLY accountpassword
643- ADD CONSTRAINT accountpassword_pkey PRIMARY KEY (id);
644-
645-
646---
647--- Name: authtoken__token__key; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
648---
649-
650-ALTER TABLE ONLY authtoken
651- ADD CONSTRAINT authtoken__token__key UNIQUE (token);
652-
653-
654---
655--- Name: authtoken_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
656---
657-
658-ALTER TABLE ONLY authtoken
659- ADD CONSTRAINT authtoken_pkey PRIMARY KEY (id);
660-
661-
662---
663--- Name: emailaddress_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
664---
665-
666-ALTER TABLE ONLY emailaddress
667- ADD CONSTRAINT emailaddress_pkey PRIMARY KEY (id);
668-
669-
670---
671--- Name: openidassociation_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
672---
673-
674-ALTER TABLE ONLY openidassociation
675- ADD CONSTRAINT openidassociation_pkey PRIMARY KEY (server_url, handle);
676-
677-
678---
679--- Name: openidauthorization_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
680---
681-
682-ALTER TABLE ONLY openidauthorization
683- ADD CONSTRAINT openidauthorization_pkey PRIMARY KEY (id);
684-
685-
686---
687--- Name: openidnonce_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
688---
689-
690-ALTER TABLE ONLY openidnonce
691- ADD CONSTRAINT openidnonce_pkey PRIMARY KEY (server_url, "timestamp", salt);
692-
693-
694---
695--- Name: openidrpsummary__account__trust_root__openid_identifier__key; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
696---
697-
698-ALTER TABLE ONLY openidrpsummary
699- ADD CONSTRAINT openidrpsummary__account__trust_root__openid_identifier__key UNIQUE (account, trust_root, openid_identifier);
700-
701-
702---
703--- Name: openidrpsummary_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
704---
705-
706-ALTER TABLE ONLY openidrpsummary
707- ADD CONSTRAINT openidrpsummary_pkey PRIMARY KEY (id);
708-
709-
710---
711--- Name: account__old_openid_identifier__idx; Type: INDEX; Schema: public; Owner: -; Tablespace:
712---
713-
714-CREATE INDEX account__old_openid_identifier__idx ON account USING btree (old_openid_identifier);
715-
716-
717---
718--- Name: authtoken__date_consumed__idx; Type: INDEX; Schema: public; Owner: -; Tablespace:
719---
720-
721-CREATE INDEX authtoken__date_consumed__idx ON authtoken USING btree (date_consumed);
722-
723-
724---
725--- Name: authtoken__date_created__idx; Type: INDEX; Schema: public; Owner: -; Tablespace:
726---
727-
728-CREATE INDEX authtoken__date_created__idx ON authtoken USING btree (date_created);
729-
730-
731---
732--- Name: authtoken__requester__idx; Type: INDEX; Schema: public; Owner: -; Tablespace:
733---
734-
735-CREATE INDEX authtoken__requester__idx ON authtoken USING btree (requester);
736-
737-
738---
739--- Name: emailaddress__account__key; Type: INDEX; Schema: public; Owner: -; Tablespace:
740---
741-
742-CREATE UNIQUE INDEX emailaddress__account__key ON emailaddress USING btree (account) WHERE ((status = 4) AND (account IS NOT NULL));
743-
744-
745---
746--- Name: INDEX emailaddress__account__key; Type: COMMENT; Schema: public; Owner: -
747---
748-
749-COMMENT ON INDEX emailaddress__account__key IS 'Ensures that an Account only has one preferred email address';
750-
751-
752---
753--- Name: emailaddress__lower_email__key; Type: INDEX; Schema: public; Owner: -; Tablespace:
754---
755-
756-CREATE INDEX emailaddress__lower_email__key ON emailaddress USING btree (lower(email));
757-
758-
759---
760--- Name: emailaddress__person__key; Type: INDEX; Schema: public; Owner: -; Tablespace:
761---
762-
763-CREATE UNIQUE INDEX emailaddress__person__key ON emailaddress USING btree (person) WHERE ((status = 4) AND (person IS NOT NULL));
764-
765-
766---
767--- Name: INDEX emailaddress__person__key; Type: COMMENT; Schema: public; Owner: -
768---
769-
770-COMMENT ON INDEX emailaddress__person__key IS 'Ensures that a Person only has one preferred email address';
771-
772-
773---
774--- Name: emailaddress__person__status__idx; Type: INDEX; Schema: public; Owner: -; Tablespace:
775---
776-
777-CREATE INDEX emailaddress__person__status__idx ON emailaddress USING btree (person, status);
778-
779-
780---
781--- Name: openidauthorixation__account__troot__expires__client_id__idx; Type: INDEX; Schema: public; Owner: -; Tablespace:
782---
783-
784-CREATE INDEX openidauthorixation__account__troot__expires__client_id__idx ON openidauthorization USING btree (account, trust_root, date_expires, client_id);
785-
786-
787---
788--- Name: openidauthorixation__account__trust_root__key; Type: INDEX; Schema: public; Owner: -; Tablespace:
789---
790-
791-CREATE UNIQUE INDEX openidauthorixation__account__trust_root__key ON openidauthorization USING btree (account, trust_root) WHERE (client_id IS NULL);
792-
793-
794---
795--- Name: openidauthorization__account__client_id__trust_root__key; Type: INDEX; Schema: public; Owner: -; Tablespace:
796---
797-
798-CREATE UNIQUE INDEX openidauthorization__account__client_id__trust_root__key ON openidauthorization USING btree (account, client_id, trust_root) WHERE (client_id IS NOT NULL);
799-
800-
801---
802--- Name: openidrpsummary__openid_identifier__idx; Type: INDEX; Schema: public; Owner: -; Tablespace:
803---
804-
805-CREATE INDEX openidrpsummary__openid_identifier__idx ON openidrpsummary USING btree (openid_identifier);
806-
807-
808---
809--- Name: openidrpsummary__trust_root__idx; Type: INDEX; Schema: public; Owner: -; Tablespace:
810---
811-
812-CREATE INDEX openidrpsummary__trust_root__idx ON openidrpsummary USING btree (trust_root);
813-
814-
815---
816--- Name: _sl_logtrigger_200; Type: TRIGGER; Schema: public; Owner: -
817---
818-
819-CREATE TRIGGER _sl_logtrigger_200
820- AFTER INSERT OR DELETE OR UPDATE ON account
821- FOR EACH ROW
822- EXECUTE PROCEDURE _sl.logtrigger('_sl', '200', 'kvvvvvvvv');
823-
824-
825---
826--- Name: _sl_logtrigger_201; Type: TRIGGER; Schema: public; Owner: -
827---
828-
829-CREATE TRIGGER _sl_logtrigger_201
830- AFTER INSERT OR DELETE OR UPDATE ON accountpassword
831- FOR EACH ROW
832- EXECUTE PROCEDURE _sl.logtrigger('_sl', '201', 'kvv');
833-
834-
835---
836--- Name: _sl_logtrigger_274; Type: TRIGGER; Schema: public; Owner: -
837---
838-
839-CREATE TRIGGER _sl_logtrigger_274
840- AFTER INSERT OR DELETE OR UPDATE ON emailaddress
841- FOR EACH ROW
842- EXECUTE PROCEDURE _sl.logtrigger('_sl', '274', 'kvvvvv');
843-
844-
845---
846--- Name: _sl_logtrigger_335; Type: TRIGGER; Schema: public; Owner: -
847---
848-
849-CREATE TRIGGER _sl_logtrigger_335
850- AFTER INSERT OR DELETE OR UPDATE ON openidauthorization
851- FOR EACH ROW
852- EXECUTE PROCEDURE _sl.logtrigger('_sl', '335', 'kvvvvv');
853-
854-
855---
856--- Name: _sl_logtrigger_337; Type: TRIGGER; Schema: public; Owner: -
857---
858-
859-CREATE TRIGGER _sl_logtrigger_337
860- AFTER INSERT OR DELETE OR UPDATE ON openidrpsummary
861- FOR EACH ROW
862- EXECUTE PROCEDURE _sl.logtrigger('_sl', '337', 'kvvvvvv');
863-
864-
865---
866--- Name: _sl_logtrigger_438; Type: TRIGGER; Schema: public; Owner: -
867---
868-
869-CREATE TRIGGER _sl_logtrigger_438
870- AFTER INSERT OR DELETE OR UPDATE ON authtoken
871- FOR EACH ROW
872- EXECUTE PROCEDURE _sl.logtrigger('_sl', '438', 'kvvvvvvvv');
873-
874-
875---
876--- Name: _sl_logtrigger_439; Type: TRIGGER; Schema: public; Owner: -
877---
878-
879-CREATE TRIGGER _sl_logtrigger_439
880- AFTER INSERT OR DELETE OR UPDATE ON openidassociation
881- FOR EACH ROW
882- EXECUTE PROCEDURE _sl.logtrigger('_sl', '439', 'kkvvvv');
883-
884-
885---
886--- Name: _sl_logtrigger_445; Type: TRIGGER; Schema: public; Owner: -
887---
888-
889-CREATE TRIGGER _sl_logtrigger_445
890- AFTER INSERT OR DELETE OR UPDATE ON openidnonce
891- FOR EACH ROW
892- EXECUTE PROCEDURE _sl.logtrigger('_sl', '445', 'kkk');
893-
894-
895---
896--- Name: set_date_status_set_t; Type: TRIGGER; Schema: public; Owner: -
897---
898-
899-CREATE TRIGGER set_date_status_set_t
900- BEFORE UPDATE ON account
901- FOR EACH ROW
902- EXECUTE PROCEDURE set_date_status_set();
903-
904-
905---
906--- Name: accountpassword_account_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
907---
908-
909-ALTER TABLE ONLY accountpassword
910- ADD CONSTRAINT accountpassword_account_fkey FOREIGN KEY (account) REFERENCES account(id) ON DELETE CASCADE;
911-
912-
913---
914--- Name: authtoken__requester__fk; Type: FK CONSTRAINT; Schema: public; Owner: -
915---
916-
917-ALTER TABLE ONLY authtoken
918- ADD CONSTRAINT authtoken__requester__fk FOREIGN KEY (requester) REFERENCES account(id);
919-
920-
921---
922--- Name: emailaddress__account__fk; Type: FK CONSTRAINT; Schema: public; Owner: -
923---
924-
925-ALTER TABLE ONLY emailaddress
926- ADD CONSTRAINT emailaddress__account__fk FOREIGN KEY (account) REFERENCES account(id) ON DELETE SET NULL;
927-
928-
929---
930--- Name: openidauthorization__account__fk; Type: FK CONSTRAINT; Schema: public; Owner: -
931---
932-
933-ALTER TABLE ONLY openidauthorization
934- ADD CONSTRAINT openidauthorization__account__fk FOREIGN KEY (account) REFERENCES account(id);
935-
936-
937---
938--- Name: openidrpsummary_account_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
939---
940-
941-ALTER TABLE ONLY openidrpsummary
942- ADD CONSTRAINT openidrpsummary_account_fkey FOREIGN KEY (account) REFERENCES account(id);
943-
944-
945---
946--- PostgreSQL database dump complete
947---
948-
949-CREATE INDEX emailaddress__account__status__idx
950- ON EmailAddress(account, status);
951-
952-
953--- Permissions for Ubuntu SSO server testing on staging.
954-
955--- Mirrored from sso_auth user 2010-01-12.
956--- These tables will eventually not be available.
957---
958-GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE account TO ubuntu_sso;
959-GRANT USAGE ON SEQUENCE account_id_seq TO ubuntu_sso;
960-GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE accountpassword TO ubuntu_sso;
961-GRANT USAGE ON SEQUENCE accountpassword_id_seq TO ubuntu_sso;
962-GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE authtoken TO ubuntu_sso;
963-GRANT USAGE ON SEQUENCE authtoken_id_seq TO ubuntu_sso;
964-GRANT SELECT ON TABLE person TO ubuntu_sso;
965-GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE emailaddress TO ubuntu_sso;
966-GRANT USAGE ON SEQUENCE emailaddress_id_seq TO ubuntu_sso;
967-GRANT SELECT,INSERT,DELETE ON TABLE openidassociation TO ubuntu_sso;
968-GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE openidauthorization TO ubuntu_sso;
969-GRANT USAGE ON SEQUENCE openidauthorization_id_seq TO ubuntu_sso;
970-GRANT SELECT,INSERT,DELETE ON TABLE openidnonce TO ubuntu_sso;
971-GRANT SELECT,INSERT,UPDATE ON TABLE openidrpsummary TO ubuntu_sso;
972-GRANT USAGE ON SEQUENCE openidrpsummary_id_seq TO ubuntu_sso;
973-GRANT SELECT ON SEQUENCE person_id_seq TO ubuntu_sso;
974-GRANT SELECT ON TABLE personlocation TO ubuntu_sso;
975-GRANT SELECT ON SEQUENCE personlocation_id_seq TO ubuntu_sso;
976-GRANT SELECT ON TABLE teamparticipation TO ubuntu_sso;
977-GRANT SELECT ON SEQUENCE teamparticipation_id_seq TO ubuntu_sso;
978-
979--- Permissions on the Ubuntu SSO tables.
980---
981-GRANT SELECT, INSERT, DELETE, UPDATE ON TABLE auth_permission,
982-auth_group_permissions, auth_group, auth_user, auth_user_groups,
983-auth_user_user_permissions, auth_message, django_content_type,
984-django_session, django_site, django_admin_log,
985-ssoopenidrpconfig TO ubuntu_sso;
986-
987-GRANT USAGE ON SEQUENCE auth_group_id_seq,
988-auth_group_permissions_id_seq, auth_message_id_seq,
989-auth_permission_id_seq, auth_user_groups_id_seq, auth_user_id_seq,
990-auth_user_user_permissions_id_seq, django_admin_log_id_seq,
991-django_content_type_id_seq, django_site_id_seq,
992-ssoopenidrpconfig_id_seq TO ubuntu_sso;
993-
994--- Permissions on the lpmirror tables (mirrors of relevant Launchpad
995--- information, available even when Launchpad database upgrades are in
996--- progress).
997-GRANT SELECT
998-ON TABLE
999- lp_person, lp_personlocation, lp_teamparticipation, lp_account
1000-TO ubuntu_sso;
1001-
1002
1003=== removed file 'database/replication/authdb_drop.sql'
1004--- database/replication/authdb_drop.sql 2009-11-11 10:32:35 +0000
1005+++ database/replication/authdb_drop.sql 1970-01-01 00:00:00 +0000
1006@@ -1,14 +0,0 @@
1007--- Copyright 2009 Canonical Ltd. This software is licensed under the
1008--- GNU Affero General Public License version 3 (see the file LICENSE).
1009-
1010-SET client_min_messages=ERROR;
1011-
1012--- Drop everything in the authdb replication set.
1013-DROP TABLE IF EXISTS Account CASCADE;
1014-DROP TABLE IF EXISTS AccountPassword CASCADE;
1015-DROP TABLE IF EXISTS AuthToken CASCADE;
1016-DROP TABLE IF EXISTS EmailAddress CASCADE;
1017-DROP TABLE IF EXISTS OpenIDAssociation CASCADE;
1018-DROP TABLE IF EXISTS OpenIDAuthorization CASCADE;
1019-DROP TABLE IF EXISTS OpenIDNonce CASCADE;
1020-DROP TABLE IF EXISTS OpenIDRPSummary;
1021
1022=== removed file 'database/replication/authdb_sequences.sql'
1023--- database/replication/authdb_sequences.sql 2010-01-13 06:54:32 +0000
1024+++ database/replication/authdb_sequences.sql 1970-01-01 00:00:00 +0000
1025@@ -1,22 +0,0 @@
1026--- Repair sequences in the authdb replication set. We need to do this because
1027--- we cannot restore the sequence values from the dump when restoring the
1028--- data using pg_restore --data-only.
1029-
1030-SELECT setval('account_id_seq', max(id)) AS Account
1031-FROM Account;
1032-
1033-SELECT setval('accountpassword_id_seq', max(id)) AS AccountPassword
1034-FROM AccountPassword;
1035-
1036-SELECT setval('authtoken_id_seq', max(id)) AS AuthToken
1037-FROM AuthToken;
1038-
1039-SELECT setval('emailaddress_id_seq', max(id)) AS EmailAddress
1040-FROM EmailAddress;
1041-
1042-SELECT setval('openidauthorization_id_seq', max(id)) AS OpenIDAuthorization
1043-FROM OpenIDAuthorization;
1044-
1045-SELECT setval('openidrpsummary_id_seq', max(id)) AS OpenIDRPSummary
1046-FROM OpenIDRPSummary;
1047-
1048
1049=== modified file 'database/replication/helpers.py'
1050--- database/replication/helpers.py 2010-04-01 09:29:27 +0000
1051+++ database/replication/helpers.py 2010-04-13 06:35:59 +0000
1052@@ -28,20 +28,15 @@
1053
1054 # Replication set id constants. Don't change these without DBA help.
1055 LPMAIN_SET_ID = 1
1056-AUTHDB_SET_ID = 2
1057 HOLDING_SET_ID = 666
1058+LPMIRROR_SET_ID = 4
1059
1060-# Seed tables for the authdb replication set to be passed to
1061+# Seed tables for the lpmain replication set to be passed to
1062 # calculate_replication_set().
1063-AUTHDB_SEED = frozenset([
1064+LPMAIN_SEED = frozenset([
1065 ('public', 'account'),
1066+ ('public', 'openidnonce'),
1067 ('public', 'openidassociation'),
1068- ('public', 'openidnonce'),
1069- ])
1070-
1071-# Seed tables for the lpmain replication set to be passed to
1072-# calculate_replication_set().
1073-LPMAIN_SEED = frozenset([
1074 ('public', 'person'),
1075 ('public', 'launchpaddatabaserevision'),
1076 ('public', 'databasereplicationlag'),
1077@@ -57,7 +52,6 @@
1078 ('public', 'launchpadstatistic'),
1079 ('public', 'parsedapachelog'),
1080 ('public', 'shipitsurvey'),
1081- ('public', 'openidassociations'), # Remove this in April 2009 or later.
1082 ('public', 'databasereplicationlag'),
1083 ])
1084
1085@@ -177,12 +171,13 @@
1086 script = preamble() + script
1087
1088 if sync is not None:
1089- script = script + dedent("""\
1090+ sync_script = dedent("""\
1091 sync (id = @master_node);
1092 wait for event (
1093- origin = ALL, confirmed = ALL,
1094+ origin = @master_node, confirmed = ALL,
1095 wait on = @master_node, timeout = %d);
1096 """ % sync)
1097+ script = script + sync_script
1098
1099 # Copy the script to a NamedTemporaryFile rather than just pumping it
1100 # to slonik via stdin. This way it can be examined if slonik appears
1101@@ -193,7 +188,7 @@
1102
1103 # Run slonik
1104 log.debug("Executing slonik script %s" % script_on_disk.name)
1105- log.log(DEBUG2, script)
1106+ log.log(DEBUG2, 'Running script:\n%s' % script)
1107 returncode = subprocess.call(['slonik', script_on_disk.name])
1108
1109 if returncode != 0:
1110@@ -324,10 +319,10 @@
1111 cluster name = sl;
1112
1113 # Symbolic ids for replication sets.
1114- define lpmain_set %d;
1115- define authdb_set %d;
1116- define holding_set %d;
1117- """ % (LPMAIN_SET_ID, AUTHDB_SET_ID, HOLDING_SET_ID))]
1118+ define lpmain_set %d;
1119+ define holding_set %d;
1120+ define lpmirror_set %d;
1121+ """ % (LPMAIN_SET_ID, HOLDING_SET_ID, LPMIRROR_SET_ID))]
1122
1123 if master_node is not None:
1124 preamble.append(dedent("""\
1125@@ -504,19 +499,6 @@
1126 raise ReplicationConfigError(
1127 "Unreplicated sequences: %s" % repr(unrepl_sequences))
1128
1129- authdb_tables, authdb_sequences = calculate_replication_set(
1130- cur, AUTHDB_SEED)
1131 lpmain_tables, lpmain_sequences = calculate_replication_set(
1132 cur, LPMAIN_SEED)
1133
1134- confused_tables = authdb_tables.intersection(lpmain_tables)
1135- if confused_tables:
1136- raise ReplicationConfigError(
1137- "Tables exist in multiple replication sets: %s"
1138- % repr(confused_tables))
1139- confused_sequences = authdb_sequences.intersection(lpmain_sequences)
1140- if confused_sequences:
1141- raise ReplicationConfigError(
1142- "Sequences exist in multiple replication sets: %s"
1143- % repr(confused_sequences))
1144-
1145
1146=== modified file 'database/replication/initialize.py'
1147--- database/replication/initialize.py 2010-04-07 21:26:08 +0000
1148+++ database/replication/initialize.py 2010-04-13 06:35:59 +0000
1149@@ -88,54 +88,13 @@
1150 helpers.sync(120) # Will exit on failure.
1151
1152
1153-def create_replication_sets(
1154- authdb_tables, authdb_sequences, lpmain_tables, lpmain_sequences):
1155+def create_replication_sets(lpmain_tables, lpmain_sequences):
1156 """Create the replication sets."""
1157 log.info('Creating Slony-I replication sets.')
1158
1159- # Instead of creating both the authdb and lpmain replication sets,
1160- # we just create the lpmain replication set containing everything.
1161- # This way, we can then test the populate_auth_replication_set.py
1162- # migration script that moves the relevant tables from the lpmain
1163- # replication set to the authdb replication set.
1164- # We will turn this behavior off once we are running two
1165- # replication sets in production and remove the migration script.
1166- lpmain_tables = lpmain_tables.union(authdb_tables)
1167- lpmain_sequences = lpmain_sequences.union(authdb_sequences)
1168-
1169 script = ["try {"]
1170- # script,append("""
1171- # echo 'Creating AuthDB replication set (@authdb_set)';
1172- # create set (
1173- # id=@authdb_set, origin=@master_node,
1174- # comment='AuthDB tables and sequences');
1175- # """)
1176
1177- # entry_id = 1
1178- # for table in sorted(authdb_tables):
1179- # script.append("""
1180- # echo 'Adding %(table)s to replication set @authdb_set';
1181- # set add table (
1182- # set id=@authdb_set,
1183- # origin=@master_node,
1184- # id=%(entry_id)d,
1185- # fully qualified name='%(table)s');
1186- # """ % vars())
1187- # entry_id += 1
1188- # entry_id = 1
1189- # for sequence in sorted(authdb_sequences):
1190- # script.append("""
1191- # echo 'Adding %(sequence)s to replication set @authdb_set';
1192- # set add sequence (
1193- # set id=@authdb_set,
1194- # origin=@master_node,
1195- # id=%(entry_id)d,
1196- # fully qualified name='%(sequence)s');
1197- # """ % vars())
1198- # entry_id += 1
1199- #
1200- # assert entry_id < 200, 'authdb replcation set has > 200 objects???'
1201- entry_id = 200
1202+ entry_id = 1
1203
1204 script.append("""
1205 echo 'Creating LPMain replication set (@lpmain_set)';
1206@@ -157,7 +116,7 @@
1207 """ % vars())
1208 entry_id += 1
1209
1210- entry_id = 200
1211+ entry_id = 1
1212 script.append(
1213 "echo 'Adding %d sequences to replication set @lpmain_set';"
1214 % len(lpmain_sequences))
1215@@ -199,9 +158,6 @@
1216 con.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
1217 global cur
1218 cur = con.cursor()
1219- log.debug("Calculating authdb replication set.")
1220- authdb_tables, authdb_sequences = helpers.calculate_replication_set(
1221- cur, helpers.AUTHDB_SEED)
1222 log.debug("Calculating lpmain replication set.")
1223 lpmain_tables, lpmain_sequences = helpers.calculate_replication_set(
1224 cur, helpers.LPMAIN_SEED)
1225@@ -212,8 +168,7 @@
1226 fails = 0
1227 for table in all_tables_in_schema(cur, 'public'):
1228 times_seen = 0
1229- for table_set in [
1230- authdb_tables, lpmain_tables, helpers.IGNORED_TABLES]:
1231+ for table_set in [lpmain_tables, helpers.IGNORED_TABLES]:
1232 if table in table_set:
1233 times_seen += 1
1234 if times_seen == 0:
1235@@ -224,8 +179,7 @@
1236 fails += 1
1237 for sequence in all_sequences_in_schema(cur, 'public'):
1238 times_seen = 0
1239- for sequence_set in [
1240- authdb_sequences, lpmain_sequences, helpers.IGNORED_SEQUENCES]:
1241+ for sequence_set in [lpmain_sequences, helpers.IGNORED_SEQUENCES]:
1242 if sequence in sequence_set:
1243 times_seen += 1
1244 if times_seen == 0:
1245@@ -242,8 +196,7 @@
1246
1247 ensure_live()
1248
1249- create_replication_sets(
1250- authdb_tables, authdb_sequences, lpmain_tables, lpmain_sequences)
1251+ create_replication_sets(lpmain_tables, lpmain_sequences)
1252
1253 helpers.sync(0)
1254
1255
1256=== modified file 'database/replication/new-slave.py'
1257--- database/replication/new-slave.py 2010-04-07 21:26:08 +0000
1258+++ database/replication/new-slave.py 2010-04-13 06:35:59 +0000
1259@@ -22,10 +22,9 @@
1260 from canonical.database.sqlbase import (
1261 connect_string, ISOLATION_LEVEL_AUTOCOMMIT)
1262 from canonical.launchpad.scripts import db_options, logger_options, logger
1263-from canonical.launchpad.webapp.adapter import _auth_store_tables
1264
1265 import replication.helpers
1266-from replication.helpers import AUTHDB_SET_ID, LPMAIN_SET_ID
1267+from replication.helpers import LPMAIN_SET_ID
1268
1269 def main():
1270 parser = OptionParser(
1271@@ -77,8 +76,6 @@
1272 # Get the connection string for masters.
1273 lpmain_connection_string = get_master_connection_string(
1274 source_connection, parser, LPMAIN_SET_ID) or source_connection_string
1275- authdb_connection_string = get_master_connection_string(
1276- source_connection, parser, AUTHDB_SET_ID) or source_connection_string
1277
1278 # Sanity check the target connection string.
1279 target_connection_string = ConnectionString(raw_target_connection_string)
1280@@ -130,31 +127,6 @@
1281 log.error("Failed to duplicate database schema.")
1282 return 1
1283
1284- # Drop the authdb replication set tables we just restored, as they
1285- # will be broken if the authdb master is a seperate database to the
1286- # lpmain master.
1287- log.debug("Dropping (possibly corrupt) authdb tables.")
1288- cur = target_con.cursor()
1289- for table_name in _auth_store_tables:
1290- cur.execute("DROP TABLE IF EXISTS %s CASCADE" % table_name)
1291- target_con.commit()
1292-
1293- # Duplicate the authdb schema.
1294- log.info("Duplicating authdb schema from '%s' to '%s'" % (
1295- authdb_connection_string, target_connection_string))
1296- table_args = ["--table=%s" % table for table in _auth_store_tables]
1297- # We need to restore the two cross-replication-set views that where
1298- # dropped as a side effect of dropping the auth store tables.
1299- table_args.append("--table=ValidPersonCache")
1300- table_args.append("--table=ValidPersonOrTeamCache")
1301- cmd = "pg_dump --schema-only --no-privileges %s %s | psql -1 -q %s" % (
1302- ' '.join(table_args),
1303- source_connection_string.asPGCommandLineArgs(),
1304- target_connection_string.asPGCommandLineArgs())
1305- if subprocess.call(cmd, shell=True) != 0:
1306- log.error("Failed to duplicate database schema.")
1307- return 1
1308-
1309 # Trash the broken Slony tables we just duplicated.
1310 log.debug("Removing slony cruft.")
1311 cur = target_con.cursor()
1312@@ -163,21 +135,30 @@
1313 del target_con
1314
1315 # Get a list of existing set ids that can be subscribed too. This
1316- # is all sets where the origin is the master_node, and set 2 if
1317- # the master happens to be configured as a forwarding slave. We
1318+ # is all sets where the origin is the master_node. We
1319 # don't allow other sets where the master is configured as a
1320 # forwarding slave as we have to special case rebuilding the database
1321- # schema (such as we do for the authdb replication set 2).
1322+ # schema, and we want to avoid cascading slave configurations anyway
1323+ # since we are running an antique Slony-I at the moment - keep it
1324+ # simple!
1325+ # We order the sets smallest to largest by number of tables.
1326+ # This should let us subscribe the quickest sets first for more
1327+ # immediate feedback.
1328 source_connection.rollback()
1329 master_node = replication.helpers.get_master_node(source_connection)
1330 cur = source_connection.cursor()
1331 cur.execute("""
1332- SELECT set_id FROM _sl.sl_set WHERE set_origin=%d
1333- UNION
1334- SELECT sub_set AS set_id FROM _sl.sl_subscribe
1335- WHERE sub_receiver=%d AND sub_forward IS TRUE AND sub_active IS TRUE
1336- AND sub_set=2
1337- """ % (master_node.node_id, master_node.node_id))
1338+ SELECT set_id
1339+ FROM _sl.sl_set, (
1340+ SELECT tab_set, count(*) AS tab_count
1341+ FROM _sl.sl_table GROUP BY tab_set
1342+ ) AS TableCounts
1343+ WHERE
1344+ set_origin=%d
1345+ AND tab_set = set_id
1346+ ORDER BY tab_count
1347+ """
1348+ % (master_node.node_id,))
1349 set_ids = [set_id for set_id, in cur.fetchall()]
1350 log.debug("Discovered set ids %s" % repr(list(set_ids)))
1351
1352@@ -209,19 +190,32 @@
1353 } on error { echo 'Failed.'; exit 1; }
1354 """)
1355
1356+ full_sync = []
1357+ sync_nicknames = [node.nickname for node in existing_nodes]
1358+ sync_nicknames.append('new_node');
1359+ for nickname in sync_nicknames:
1360+ full_sync.append(dedent("""\
1361+ echo 'Waiting for %(nickname)s sync.';
1362+ sync (id=@%(nickname)s);
1363+ wait for event (
1364+ origin = @%(nickname)s, confirmed=ALL,
1365+ wait on = @%(nickname)s, timeout=0);
1366+ """ % {'nickname': nickname}))
1367+ full_sync = '\n'.join(full_sync)
1368+ script += full_sync
1369+
1370 for set_id in set_ids:
1371-
1372 script += dedent("""\
1373 echo 'Subscribing new node to set %d.';
1374 subscribe set (
1375 id=%d, provider=@master_node, receiver=@new_node, forward=yes);
1376-
1377- echo 'Waiting for sync... this might take a while...';
1378+ echo 'Waiting for subscribe to start processing.';
1379 sync (id = @master_node);
1380 wait for event (
1381- origin = ALL, confirmed = ALL,
1382+ origin = @master_node, confirmed = ALL,
1383 wait on = @master_node, timeout = 0);
1384 """ % (set_id, set_id))
1385+ script += full_sync
1386
1387 replication.helpers.execute_slonik(script)
1388
1389
1390=== removed file 'database/replication/populate_auth_replication_set.py'
1391--- database/replication/populate_auth_replication_set.py 2010-04-07 21:26:08 +0000
1392+++ database/replication/populate_auth_replication_set.py 1970-01-01 00:00:00 +0000
1393@@ -1,177 +0,0 @@
1394-#!/usr/bin/python2.5 -S
1395-#
1396-# Copyright 2009 Canonical Ltd. This software is licensed under the
1397-# GNU Affero General Public License version 3 (see the file LICENSE).
1398-
1399-"""Populate the auth replication set.
1400-
1401-This script moves the the SSO tables from the main replication set to
1402-the auth replication set.
1403-
1404-Once it has been run on production, these tables can no longer be
1405-maintained using the Launchpad database maintenance scripts
1406-(upgrade.py, security.py etc.).
1407-
1408-We do this so Launchpad database upgrades do not lock the SSO tables,
1409-allowing the SSO service to continue to operate.
1410-
1411-This is a single shot script.
1412-"""
1413-
1414-__metaclass__ = type
1415-__all__ = []
1416-
1417-import _pythonpath
1418-
1419-import sys
1420-from textwrap import dedent
1421-from optparse import OptionParser
1422-
1423-from canonical.database.sqlbase import (
1424- connect, ISOLATION_LEVEL_AUTOCOMMIT, sqlvalues)
1425-from canonical.launchpad.scripts import db_options, logger_options, logger
1426-
1427-import replication.helpers
1428-
1429-def create_auth_set(cur):
1430- """Create the auth replication set if it doesn't already exist."""
1431- cur.execute("SELECT TRUE FROM _sl.sl_set WHERE set_id=2")
1432- if cur.fetchone() is not None:
1433- log.info("Auth set already exists.")
1434- return
1435- slonik_script = dedent("""\
1436- create set (
1437- id=@authdb_set, origin=@master_node,
1438- comment='SSO service tables');
1439- """)
1440- log.info("Creating authdb replication set.")
1441- replication.helpers.execute_slonik(slonik_script, sync=0)
1442-
1443-
1444-def subscribe_auth_set(cur):
1445- """The authdb set subscription much match the lpmain set subscription.
1446-
1447- This is a requirement to move stuff between replication sets. It
1448- is also what we want (all nodes replicating everything).
1449- """
1450- cur.execute("""
1451- SELECT sub_receiver FROM _sl.sl_subscribe WHERE sub_set = 1
1452- EXCEPT
1453- SELECT sub_receiver FROM _sl.sl_subscribe WHERE sub_set = 2
1454- """)
1455- for node_id in (node_id for node_id, in cur.fetchall()):
1456- log.info("Subscribing Node #%d to authdb replication set" % node_id)
1457- success = replication.helpers.execute_slonik(dedent("""\
1458- subscribe set (
1459- id = @authdb_set, provider = @master_node,
1460- receiver = %d, forward = yes);
1461- """ % node_id), sync=0)
1462- if not success:
1463- log.error("Slonik failed. Exiting.")
1464- sys.exit(1)
1465-
1466-
1467-def migrate_tables_and_sequences(cur):
1468- auth_tables, auth_sequences = (
1469- replication.helpers.calculate_replication_set(
1470- cur, replication.helpers.AUTHDB_SEED))
1471-
1472- slonik_script = ["try {"]
1473- for table_fqn in auth_tables:
1474- namespace, table_name = table_fqn.split('.')
1475- cur.execute("""
1476- SELECT tab_id, tab_set
1477- FROM _sl.sl_table
1478- WHERE tab_nspname = %s AND tab_relname = %s
1479- """ % sqlvalues(namespace, table_name))
1480- try:
1481- table_id, set_id = cur.fetchone()
1482- except IndexError:
1483- log.error("Table %s not found in _sl.sl_tables" % table_fqn)
1484- sys.exit(1)
1485- if set_id == 1:
1486- slonik_script.append("echo 'Moving table %s';" % table_fqn)
1487- slonik_script.append(
1488- "set move table "
1489- "(origin=@master_node, id=%d, new set=@authdb_set);"
1490- % table_id)
1491- elif set_id == 2:
1492- log.warn(
1493- "Table %s already in authdb replication set"
1494- % table_fqn)
1495- else:
1496- log.error("Unknown replication set %s" % set_id)
1497- sys.exit(1)
1498-
1499- for sequence_fqn in auth_sequences:
1500- namespace, sequence_name = sequence_fqn.split('.')
1501- cur.execute("""
1502- SELECT seq_id, seq_set
1503- FROM _sl.sl_sequence
1504- WHERE seq_nspname = %s AND seq_relname = %s
1505- """ % sqlvalues(namespace, sequence_name))
1506- try:
1507- sequence_id, set_id = cur.fetchone()
1508- except IndexError:
1509- log.error(
1510- "Sequence %s not found in _sl.sl_sequences" % sequence_fqn)
1511- sys.exit(1)
1512- if set_id == 1:
1513- slonik_script.append("echo 'Moving sequence %s';" % sequence_fqn)
1514- slonik_script.append(
1515- "set move sequence "
1516- "(origin=@master_node, id=%d, new set=@authdb_set);"
1517- % sequence_id)
1518- elif set_id ==2:
1519- log.warn(
1520- "Sequence %s already in authdb replication set."
1521- % sequence_fqn)
1522- else:
1523- log.error("Unknown replication set %s" % set_id)
1524- sys.exit(1)
1525-
1526- if len(slonik_script) == 1:
1527- log.warn("No tables or sequences to migrate.")
1528- return
1529-
1530- slonik_script.append(dedent("""\
1531- } on error {
1532- echo 'Failed to move one or more tables or sequences.';
1533- exit 1;
1534- }
1535- """))
1536-
1537- slonik_script = "\n".join(slonik_script)
1538-
1539- log.info("Running migration script...")
1540- if not replication.helpers.execute_slonik(slonik_script, sync=0):
1541- log.error("Slonik failed. Exiting.")
1542- sys.exit(1)
1543-
1544-
1545-def main():
1546- parser = OptionParser()
1547- db_options(parser)
1548- logger_options(parser)
1549- options, args = parser.parse_args()
1550-
1551- global log
1552- log = logger(options)
1553-
1554- con = connect('slony', isolation=ISOLATION_LEVEL_AUTOCOMMIT)
1555- cur = con.cursor()
1556-
1557- # Don't start until cluster is synced.
1558- log.info("Waiting for sync.")
1559- replication.helpers.sync(0)
1560-
1561- create_auth_set(cur)
1562- subscribe_auth_set(cur)
1563- migrate_tables_and_sequences(cur)
1564-
1565-
1566-log = None # Global log
1567-
1568-
1569-if __name__ == '__main__':
1570- main()
1571
1572=== modified file 'database/schema/security.cfg'
1573--- database/schema/security.cfg 2010-04-12 17:02:16 +0000
1574+++ database/schema/security.cfg 2010-04-13 06:35:59 +0000
1575@@ -35,20 +35,27 @@
1576 public.is_printable_ascii(text) = EXECUTE
1577 public.launchpaddatabaserevision = SELECT
1578 public.name_blacklist_match(text) = EXECUTE
1579-public.fticache =
1580 public.pillarname = SELECT
1581 public.ulower(text) = EXECUTE
1582-public._killall_backends(text) =
1583 public.generate_openid_identifier() = EXECUTE
1584 public.getlocalnodeid() = EXECUTE
1585 public.replication_lag() = EXECUTE
1586 public.replication_lag(integer) = EXECUTE
1587 public.assert_patch_applied(integer, integer, integer) = EXECUTE
1588+# Explicitly state 'no permissions on these objects' to silence
1589+# security.py warnings.
1590+public.fticache =
1591+public._killall_backends(text) =
1592 public.exclusivelocks =
1593 public.alllocks =
1594 public.pgstattuple(oid) =
1595 public.pgstattuple(text) =
1596 public.bugnotificationarchive =
1597+public.lp_account =
1598+public.lp_personlocation =
1599+public.lp_person =
1600+public.lp_teamparticipation =
1601+public.bug_update_latest_patch_uploaded(integer) =
1602
1603 [ro]
1604 # A user with full readonly access to the database. Generally used for
1605@@ -61,59 +68,6 @@
1606 type=user
1607 groups=admin
1608
1609-[sso_auth]
1610-# authdb replication set write access from the SSO service.
1611-type=user
1612-public.account = SELECT, INSERT, UPDATE, DELETE
1613-public.accountpassword = SELECT, INSERT, UPDATE, DELETE
1614-public.authtoken = SELECT, INSERT, UPDATE, DELETE
1615-public.emailaddress = SELECT, INSERT, UPDATE, DELETE
1616-public.openidrpsummary = SELECT, INSERT, UPDATE
1617-public.openidassociation = SELECT, INSERT, DELETE
1618-public.openidnonce = SELECT, INSERT, DELETE
1619-public.openidauthorization = SELECT, INSERT, UPDATE, DELETE
1620-public.person = SELECT
1621-public.personlocation = SELECT
1622-public.teamparticipation = SELECT
1623-
1624-[sso_main]
1625-# main replication set access from the SSO service login.launchpad.net
1626-type=user
1627-public.language = SELECT
1628-public.openidrpconfig = SELECT
1629-public.person = SELECT
1630-public.personlanguage = SELECT
1631-public.personlocation = SELECT
1632-public.shippingrequest = SELECT
1633-public.teammembership = SELECT
1634-public.teamparticipation = SELECT
1635-public.validpersoncache = SELECT
1636-# Needed for person.preferredemail to work.
1637-public.emailaddress = SELECT
1638-# Needed for OpenID login to work - Bug #352727
1639-public.country = SELECT
1640-# Needed for display of OpenID consumer logo per Bug #353926
1641-public.libraryfilealias = SELECT
1642-public.libraryfilecontent = SELECT
1643-
1644-[launchpad_auth]
1645-# authdb replication set access from the main Z3 application.
1646-type=user
1647-public.account = SELECT, INSERT, UPDATE, DELETE
1648-public.accountpassword = SELECT, INSERT, UPDATE, DELETE
1649-public.authtoken = SELECT, INSERT, UPDATE
1650-public.emailaddress = SELECT, INSERT, UPDATE, DELETE
1651-public.language = SELECT
1652-public.openidrpconfig = SELECT
1653-public.openidrpsummary = SELECT
1654-public.person = SELECT
1655-public.personlanguage = SELECT
1656-public.teammembership = SELECT
1657-public.teamparticipation = SELECT
1658-# XXX 2009-05-07 stub bug=373252: SELECT and DELETE permissions required
1659-# for garbo.py. INSERT permission needed for the tests.
1660-public.openidassociation = SELECT, INSERT, DELETE
1661-
1662 [launchpad_main]
1663 # lpmain replication set access from the main Z3 application.
1664 type=user
1665
1666=== modified file 'database/schema/trusted.sql'
1667--- database/schema/trusted.sql 2010-03-26 08:25:24 +0000
1668+++ database/schema/trusted.sql 2010-04-13 06:35:59 +0000
1669@@ -1470,36 +1470,36 @@
1670
1671 -- Update the (redundant) column bug.latest_patch_uploaded when a
1672 -- a bug attachment is added or removed or if its type is changed.
1673-CREATE OR REPLACE FUNCTION bug_update_latest_patch_uploaded(integer) RETURNS VOID
1674- SECURITY DEFINER LANGUAGE plpgsql AS
1675- $$
1676- BEGIN
1677- UPDATE bug SET latest_patch_uploaded =
1678- (SELECT max(message.datecreated)
1679- FROM message, bugattachment
1680- WHERE bugattachment.message=message.id AND
1681- bugattachment.bug=$1 AND
1682- bugattachment.type=1)
1683- WHERE bug.id=$1;
1684- END;
1685- $$;
1686-
1687-
1688-CREATE OR REPLACE FUNCTION bug_update_latest_patch_uploaded_on_insert_update() RETURNS trigger
1689- SECURITY DEFINER LANGUAGE plpgsql AS
1690- $$
1691- BEGIN
1692- PERFORM bug_update_latest_patch_uploaded(NEW.bug);
1693- RETURN NULL; -- Ignored - this is an AFTER trigger
1694- END;
1695- $$;
1696-
1697-
1698-CREATE OR REPLACE FUNCTION bug_update_latest_patch_uploaded_on_delete() RETURNS trigger
1699- SECURITY DEFINER LANGUAGE plpgsql AS
1700- $$
1701- BEGIN
1702- PERFORM bug_update_latest_patch_uploaded(OLD.bug);
1703- RETURN NULL; -- Ignored - this is an AFTER trigger
1704- END;
1705- $$;
1706+CREATE OR REPLACE FUNCTION bug_update_latest_patch_uploaded(integer)
1707+RETURNS VOID SECURITY DEFINER LANGUAGE plpgsql AS
1708+$$
1709+BEGIN
1710+ UPDATE bug SET latest_patch_uploaded =
1711+ (SELECT max(message.datecreated)
1712+ FROM message, bugattachment
1713+ WHERE bugattachment.message=message.id AND
1714+ bugattachment.bug=$1 AND
1715+ bugattachment.type=1)
1716+ WHERE bug.id=$1;
1717+END;
1718+$$;
1719+
1720+
1721+CREATE OR REPLACE FUNCTION bug_update_latest_patch_uploaded_on_insert_update()
1722+RETURNS trigger SECURITY DEFINER LANGUAGE plpgsql AS
1723+$$
1724+BEGIN
1725+ PERFORM bug_update_latest_patch_uploaded(NEW.bug);
1726+ RETURN NULL; -- Ignored - this is an AFTER trigger
1727+END;
1728+$$;
1729+
1730+
1731+CREATE OR REPLACE FUNCTION bug_update_latest_patch_uploaded_on_delete()
1732+RETURNS trigger SECURITY DEFINER LANGUAGE plpgsql AS
1733+$$
1734+BEGIN
1735+ PERFORM bug_update_latest_patch_uploaded(OLD.bug);
1736+ RETURN NULL; -- Ignored - this is an AFTER trigger
1737+END;
1738+$$;

Subscribers

People subscribed via source and target branches

to status/vote changes: