Merge lp:~salgado/launchpad/remove-auth-store into lp:launchpad/db-devel

Proposed by Guilherme Salgado
Status: Merged
Merged at revision: not available
Proposed branch: lp:~salgado/launchpad/remove-auth-store
Merge into: lp:launchpad/db-devel
Diff against target: 981 lines (+108/-263)
30 files modified
configs/development/launchpad-lazr.conf (+0/-2)
configs/replicated-development/launchpad-lazr.conf (+0/-3)
configs/test-playground/launchpad-lazr.conf (+0/-2)
configs/testrunner/launchpad-lazr.conf (+0/-2)
database/schema/security.cfg (+6/-2)
lib/canonical/buildd/debian/control (+1/-1)
lib/canonical/config/__init__.py (+2/-2)
lib/canonical/config/schema-lazr.conf (+0/-8)
lib/canonical/configure.zcml (+0/-2)
lib/canonical/database/harness.py (+1/-2)
lib/canonical/database/sqlbase.py (+2/-4)
lib/canonical/database/tests/test_zopeless_transaction_manager.py (+0/-31)
lib/canonical/launchpad/database/tests/test_oauth.py (+1/-1)
lib/canonical/launchpad/doc/account.txt (+1/-26)
lib/canonical/launchpad/doc/storm.txt (+51/-71)
lib/canonical/launchpad/pagetests/standalone/xx-opstats.txt (+0/-2)
lib/canonical/launchpad/scripts/garbo.py (+5/-13)
lib/canonical/launchpad/scripts/tests/test_garbo.py (+7/-9)
lib/canonical/launchpad/webapp/adapter.py (+5/-16)
lib/canonical/launchpad/webapp/ftests/test_adapter_permissions.txt (+1/-24)
lib/canonical/launchpad/webapp/interfaces.py (+1/-3)
lib/canonical/launchpad/webapp/tests/test_dbpolicy.py (+1/-4)
lib/lp/bugs/doc/checkwatches.txt (+4/-0)
lib/lp/bugs/doc/externalbugtracker-comment-imports.txt (+3/-3)
lib/lp/code/doc/branch-karma.txt (+1/-0)
lib/lp/registry/model/person.py (+2/-17)
lib/lp/registry/stories/person/xx-admin-person-review.txt (+1/-1)
lib/lp/registry/tests/test_personset.py (+6/-10)
lib/lp/testopenid/browser/server.py (+6/-1)
utilities/sourcedeps.conf (+0/-1)
To merge this branch: bzr merge lp:~salgado/launchpad/remove-auth-store
Reviewer Review Type Date Requested Status
Stuart Bishop (community) Approve
Review via email: mp+22478@code.launchpad.net

Description of the change

Remove the auth store, together with c-i-p.

Had to grant some extra DB permissions on security.cfg because some
things that used to be done using the launchpad_auth user (the one
always used for the auth store, regardless of what was given to
initZopeless) are now done using whichever user is used by the
script/test.

 reviewer stub

--
Guilherme Salgado <email address hidden>

To post a comment you must log in.
Revision history for this message
Stuart Bishop (stub) wrote :
Download full text (5.4 KiB)

On Wed, Mar 31, 2010 at 2:00 AM, Guilherme Salgado
<email address hidden> wrote:

> Remove the auth store, together with c-i-p.
>
> Had to grant some extra DB permissions on security.cfg because some
> things that used to be done using the launchpad_auth user (the one
> always used for the auth store, regardless of what was given to
> initZopeless) are now done using whichever user is used by the
> script/test.

Yay. This is more than I expected.

> === modified file 'lib/canonical/launchpad/database/tests/test_oauth.py'
> --- lib/canonical/launchpad/database/tests/test_oauth.py 2009-06-25 05:30:52 +0000
> +++ lib/canonical/launchpad/database/tests/test_oauth.py 2010-03-30 19:00:44 +0000
> @@ -22,7 +22,7 @@
> """Base tests for the OAuth database classes."""
> layer = DatabaseFunctionalLayer
>
> - def test__get_store_should_return_the_auth_master_store(self):
> + def test__get_store_should_return_the_main_master_store(self):
> """We want all OAuth classes to use the master store.
> Otherwise, the OAuth exchanges will fail because the authorize
> screen won't probably find the new request token on the slave store.

Does this test serve any purpose any more? Maybe remove it entirely.

> === modified file 'lib/canonical/launchpad/webapp/adapter.py'
> try:
> + # XXX: Salgado, 2010-03-22: We can get rid of the realm now that
> + # the auth DB is gone, but I'm not doing it in this branch to keep
> + # the diff simple.
> config_section, realm, flavor = self._uri.database.split('-')
> except ValueError:
> raise AssertionError(
> 'Connection uri %s does not match section-realm-flavor format'
> % repr(self._uri.database))

I don't think this XXX is warranted. We may well have more realms in
the future, for example if we move translations or codehosting to
their own database for scalability reasons.

> === modified file 'lib/canonical/launchpad/webapp/ftests/test_adapter_permissions.txt'
> -
> -A MASTER_FLAVOR Store does not allow writes to tables outside of that
> -Store's replication set.
> -
> - >>> t = transaction.begin()
> - >>> person = main_master.find(Person, name='no-priv').one()
> - >>> account = person.account
> - >>> account.displayname = "Ben Dover"
> - >>> main_master.flush()
> - Traceback (most recent call last):
> - ...
> - ProgrammingError: permission denied for relation account
> - >>> transaction.abort()
> -
> - >>> t = transaction.begin()
> - >>> auth_master = getUtility(IStoreSelector).get(AUTH_STORE, MASTER_FLAVOR)
> - >>> person = auth_master.find(Person, name='no-priv').one()
> - >>> account = person.account
> - >>> account.displayname = "Ben Dover"
> - >>> auth_master.flush()
> - >>> transaction.abort()

But this crap can certainly go. If we split the database in the
future, there will be no crossover. What I've learned from the
authdb/lpmain split is that the split needs to be clean, or we end up
with confusing code (is my email address from the authdb Store or the
lpmain Store) and a complicated and tricky to maintain repl...

Read more...

review: Approve
Revision history for this message
Guilherme Salgado (salgado) wrote :
Download full text (6.8 KiB)

On Thu, 2010-04-01 at 15:12 +0000, Stuart Bishop wrote:
> Review: Approve
> On Wed, Mar 31, 2010 at 2:00 AM, Guilherme Salgado
> <email address hidden> wrote:
>
> > Remove the auth store, together with c-i-p.
> >
> > Had to grant some extra DB permissions on security.cfg because some
> > things that used to be done using the launchpad_auth user (the one
> > always used for the auth store, regardless of what was given to
> > initZopeless) are now done using whichever user is used by the
> > script/test.
>
> Yay. This is more than I expected.

More than I expected too. :/

And to make things worse, there are a couple extra revisions that
weren't in the diff you reviewed (I'm assuming you reviewed the diff
that was sent out when the m-p was created):

http://bazaar.launchpad.net/~salgado/launchpad/remove-auth-store/revision/10563
http://bazaar.launchpad.net/~salgado/launchpad/remove-auth-store/revision/10564

They're trivial, though.

>
>
>
> > === modified file 'lib/canonical/launchpad/database/tests/test_oauth.py'
> > --- lib/canonical/launchpad/database/tests/test_oauth.py 2009-06-25 05:30:52 +0000
> > +++ lib/canonical/launchpad/database/tests/test_oauth.py 2010-03-30 19:00:44 +0000
> > @@ -22,7 +22,7 @@
> > """Base tests for the OAuth database classes."""
> > layer = DatabaseFunctionalLayer
> >
> > - def test__get_store_should_return_the_auth_master_store(self):
> > + def test__get_store_should_return_the_main_master_store(self):
> > """We want all OAuth classes to use the master store.
> > Otherwise, the OAuth exchanges will fail because the authorize
> > screen won't probably find the new request token on the slave store.
>
> Does this test serve any purpose any more? Maybe remove it entirely.
>

AIUI, it's necessary because we want to make sure that we use the master
store (by default) when dealing with OAuth-related objects. (The name
of the test method was actually wrong; this is not related to the other
changes on this branch)

>
> > === modified file 'lib/canonical/launchpad/webapp/adapter.py'
> > try:
> > + # XXX: Salgado, 2010-03-22: We can get rid of the realm now that
> > + # the auth DB is gone, but I'm not doing it in this branch to keep
> > + # the diff simple.
> > config_section, realm, flavor = self._uri.database.split('-')
> > except ValueError:
> > raise AssertionError(
> > 'Connection uri %s does not match section-realm-flavor format'
> > % repr(self._uri.database))
>
> I don't think this XXX is warranted. We may well have more realms in
> the future, for example if we move translations or codehosting to
> their own database for scalability reasons.

Fair enough; I thought we'd remove that because I had never heard of
these plans.

>
> > === modified file 'lib/canonical/launchpad/webapp/ftests/test_adapter_permissions.txt'
> > -
> > -A MASTER_FLAVOR Store does not allow writes to tables outside of that
> > -Store's replication set.
> > -
> > - >>> t = transaction.begin()
> > - >>> person = main_master.find(Person, name='no-priv').one()
> > - >>> a...

Read more...

1=== modified file 'lib/canonical/launchpad/webapp/adapter.py'
2--- lib/canonical/launchpad/webapp/adapter.py 2010-03-30 17:25:52 +0000
3+++ lib/canonical/launchpad/webapp/adapter.py 2010-04-01 15:26:28 +0000
4@@ -349,9 +349,6 @@
5 raise StormAccessFromMainThread()
6
7 try:
8- # XXX: Salgado, 2010-03-22: We can get rid of the realm now that
9- # the auth DB is gone, but I'm not doing it in this branch to keep
10- # the diff simple.
11 config_section, realm, flavor = self._uri.database.split('-')
12 except ValueError:
13 raise AssertionError(
14
15=== modified file 'lib/canonical/launchpad/webapp/interfaces.py'
16--- lib/canonical/launchpad/webapp/interfaces.py 2010-03-30 17:25:52 +0000
17+++ lib/canonical/launchpad/webapp/interfaces.py 2010-04-01 15:37:19 +0000
18@@ -745,6 +745,7 @@
19 #
20
21 MAIN_STORE = 'main' # The main database.
22+ALL_STORES = frozenset([MAIN_STORE])
23
24 DEFAULT_FLAVOR = 'default' # Default flavor for current state.
25 MASTER_FLAVOR = 'master' # The master database.
26@@ -771,9 +772,6 @@
27 utility.
28 """
29
30- # XXX: 2010-03-24, Guilherme Salgado: The 'name' argument will always be
31- # MAIN_STORE here, so it can be removed. Not doing it now as this branch
32- # will be CPed into production.
33 def getStore(name, flavor):
34 """Retrieve a Store.
35
36@@ -843,9 +841,6 @@
37 def get_current():
38 """Return the currently installed `IDatabasePolicy`."""
39
40- # XXX: 2010-03-24, Guilherme Salgado: The 'name' argument will always be
41- # MAIN_STORE here, so it can be removed. Not doing it now as this branch
42- # will be CPed into production.
43 def get(name, flavor):
44 """Retrieve a Storm Store.
45
46
47=== modified file 'lib/canonical/launchpad/webapp/tests/test_dbpolicy.py'
48--- lib/canonical/launchpad/webapp/tests/test_dbpolicy.py 2010-03-24 15:22:26 +0000
49+++ lib/canonical/launchpad/webapp/tests/test_dbpolicy.py 2010-04-01 15:39:56 +0000
50@@ -25,7 +25,7 @@
51 ReadOnlyLaunchpadDatabasePolicy, SlaveDatabasePolicy,
52 SlaveOnlyDatabasePolicy)
53 from canonical.launchpad.webapp.interfaces import (
54- DEFAULT_FLAVOR, DisallowedStore, IDatabasePolicy,
55+ ALL_STORES, DEFAULT_FLAVOR, DisallowedStore, IDatabasePolicy,
56 IStoreSelector, MAIN_STORE, MASTER_FLAVOR, ReadOnlyModeDisallowedStore,
57 SLAVE_FLAVOR)
58 from canonical.launchpad.webapp.servers import LaunchpadTestRequest
59@@ -37,9 +37,10 @@
60 layer = DatabaseFunctionalLayer
61
62 def test_defaults(self):
63- self.assertProvides(
64- getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR),
65- IMasterStore)
66+ for store in ALL_STORES:
67+ self.assertProvides(
68+ getUtility(IStoreSelector).get(store, DEFAULT_FLAVOR),
69+ IMasterStore)
70
71 def test_dbusers(self):
72 store_selector = getUtility(IStoreSelector)
73@@ -79,14 +80,16 @@
74 super(SlaveDatabasePolicyTestCase, self).setUp()
75
76 def test_defaults(self):
77- self.assertProvides(
78- getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR),
79- ISlaveStore)
80+ for store in ALL_STORES:
81+ self.assertProvides(
82+ getUtility(IStoreSelector).get(store, DEFAULT_FLAVOR),
83+ ISlaveStore)
84
85 def test_master_allowed(self):
86- self.assertProvides(
87- getUtility(IStoreSelector).get(MAIN_STORE, MASTER_FLAVOR),
88- IMasterStore)
89+ for store in ALL_STORES:
90+ self.assertProvides(
91+ getUtility(IStoreSelector).get(store, MASTER_FLAVOR),
92+ IMasterStore)
93
94
95 class SlaveOnlyDatabasePolicyTestCase(SlaveDatabasePolicyTestCase):
96@@ -97,15 +100,10 @@
97 super(SlaveOnlyDatabasePolicyTestCase, self).setUp()
98
99 def test_master_allowed(self):
100- # The master store is not allowed here, but we need this empty test
101- # to overwrite the test method from our parent class, where the master
102- # store is allowed.
103- pass
104-
105- def test_master_not_allowed(self):
106- self.failUnlessRaises(
107- DisallowedStore,
108- getUtility(IStoreSelector).get, MAIN_STORE, MASTER_FLAVOR)
109+ for store in ALL_STORES:
110+ self.failUnlessRaises(
111+ DisallowedStore,
112+ getUtility(IStoreSelector).get, store, MASTER_FLAVOR)
113
114
115 class MasterDatabasePolicyTestCase(BaseDatabasePolicyTestCase):
116@@ -129,9 +127,10 @@
117
118 def test_slave_allowed(self):
119 # We get the master store even if the slave was requested.
120- self.assertProvides(
121- getUtility(IStoreSelector).get(MAIN_STORE, SLAVE_FLAVOR),
122- ISlaveStore)
123+ for store in ALL_STORES:
124+ self.assertProvides(
125+ getUtility(IStoreSelector).get(store, SLAVE_FLAVOR),
126+ ISlaveStore)
127
128
129 class LaunchpadDatabasePolicyTestCase(SlaveDatabasePolicyTestCase):
130@@ -245,20 +244,23 @@
131
132 def test_defaults(self):
133 # default Store is the slave.
134- self.assertProvides(
135- getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR),
136- ISlaveStore)
137+ for store in ALL_STORES:
138+ self.assertProvides(
139+ getUtility(IStoreSelector).get(store, DEFAULT_FLAVOR),
140+ ISlaveStore)
141
142 def test_slave_allowed(self):
143- self.assertProvides(
144- getUtility(IStoreSelector).get(MAIN_STORE, SLAVE_FLAVOR),
145- ISlaveStore)
146+ for store in ALL_STORES:
147+ self.assertProvides(
148+ getUtility(IStoreSelector).get(store, SLAVE_FLAVOR),
149+ ISlaveStore)
150
151 def test_master_disallowed(self):
152 store_selector = getUtility(IStoreSelector)
153- self.assertRaises(
154- ReadOnlyModeDisallowedStore,
155- store_selector.get, MAIN_STORE, MASTER_FLAVOR)
156+ for store in ALL_STORES:
157+ self.assertRaises(
158+ ReadOnlyModeDisallowedStore,
159+ store_selector.get, store, MASTER_FLAVOR)
160
161
162 def test_suite():
163

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'configs/development/launchpad-lazr.conf'
2--- configs/development/launchpad-lazr.conf 2010-03-05 20:49:31 +0000
3+++ configs/development/launchpad-lazr.conf 2010-04-05 12:47:32 +0000
4@@ -97,8 +97,6 @@
5 # the rw_* configs.
6 ro_main_master: dbname=launchpad_dev_template
7 ro_main_slave: dbname=launchpad_dev_template
8-auth_master: dbname=launchpad_dev
9-auth_slave: dbname=launchpad_dev
10
11 [distributionmirrorprober]
12 use_proxy: False
13
14=== modified file 'configs/replicated-development/launchpad-lazr.conf'
15--- configs/replicated-development/launchpad-lazr.conf 2010-01-05 19:09:58 +0000
16+++ configs/replicated-development/launchpad-lazr.conf 2010-04-05 12:47:32 +0000
17@@ -10,6 +10,3 @@
18 rw_main_slave: dbname=launchpad_dev_slave
19 ro_main_master: dbname=launchpad_dev
20 ro_main_slave: dbname=launchpad_dev_slave
21-auth_master: dbname=launchpad_dev
22-auth_slave: dbname=launchpad_dev_slave
23-
24
25=== modified file 'configs/test-playground/launchpad-lazr.conf'
26--- configs/test-playground/launchpad-lazr.conf 2010-01-05 19:09:58 +0000
27+++ configs/test-playground/launchpad-lazr.conf 2010-04-05 12:47:32 +0000
28@@ -10,5 +10,3 @@
29 rw_main_slave: dbname=launchpad_ftest_playground
30 ro_main_master: dbname=launchpad_ftest_playground
31 ro_main_slave: dbname=launchpad_ftest_playground
32-auth_master: dbname=launchpad_ftest_playground
33-auth_slave: dbname=launchpad_ftest_playground
34
35=== modified file 'configs/testrunner/launchpad-lazr.conf'
36--- configs/testrunner/launchpad-lazr.conf 2010-03-11 01:39:25 +0000
37+++ configs/testrunner/launchpad-lazr.conf 2010-04-05 12:47:32 +0000
38@@ -51,8 +51,6 @@
39 # the rw_* configs.
40 ro_main_master: dbname=launchpad_ftest_template
41 ro_main_slave: dbname=launchpad_ftest_template
42-auth_master: dbname=launchpad_ftest
43-auth_slave: dbname=launchpad_ftest
44 randomise_select_results: true
45
46 [error_reports]
47
48=== modified file 'database/schema/security.cfg'
49--- database/schema/security.cfg 2010-04-02 17:29:13 +0000
50+++ database/schema/security.cfg 2010-04-05 12:47:32 +0000
51@@ -118,7 +118,8 @@
52 # lpmain replication set access from the main Z3 application.
53 type=user
54 groups=write,script
55-public.account = SELECT
56+public.account = SELECT, INSERT, UPDATE, DELETE
57+public.accountpassword = SELECT, INSERT, UPDATE, DELETE
58 public.announcement = SELECT, INSERT, UPDATE, DELETE
59 public.answercontact = SELECT, INSERT, UPDATE, DELETE
60 public.apportjob = SELECT, INSERT, UPDATE, DELETE
61@@ -176,7 +177,7 @@
62 public.distributionsourcepackagecache = SELECT
63 public.distroserieslanguage = SELECT, INSERT, UPDATE
64 public.distroseriespackagecache = SELECT
65-public.emailaddress = SELECT
66+public.emailaddress = SELECT, INSERT, UPDATE, DELETE
67 public.entitlement = SELECT, INSERT, UPDATE, DELETE
68 public.faq = SELECT, INSERT, UPDATE, DELETE
69 public.featuredproject = SELECT, INSERT, DELETE
70@@ -916,6 +917,8 @@
71 # Full access except for tables that are exclusively updated by
72 # certain processes, such as the librarian tables. This group is deprecated -
73 # access should be explicitly granted to users.
74+public.account = SELECT, INSERT, UPDATE
75+public.accountpassword = SELECT, INSERT
76 public.archive = SELECT, INSERT, UPDATE
77 public.archivearch = SELECT, INSERT, UPDATE, DELETE
78 public.binarypackagerelease = SELECT, INSERT, UPDATE
79@@ -949,6 +952,7 @@
80 public.distribution = SELECT, INSERT, UPDATE
81 public.distroarchseries = SELECT, INSERT, UPDATE
82 public.distroseries = SELECT, INSERT, UPDATE
83+public.openidrpsummary = SELECT, INSERT, UPDATE
84 public.packageupload = SELECT, INSERT, UPDATE
85 public.packageuploadbuild = SELECT, INSERT, UPDATE
86 public.packageuploadsource = SELECT, INSERT, UPDATE
87
88=== modified file 'lib/canonical/buildd/debian/control'
89--- lib/canonical/buildd/debian/control 2009-11-17 22:28:43 +0000
90+++ lib/canonical/buildd/debian/control 2010-04-05 12:47:32 +0000
91@@ -8,7 +8,7 @@
92 Package: launchpad-buildd
93 Section: misc
94 Architecture: all
95-Depends: python-twisted, debootstrap, dpkg-dev, linux32, file, bzip2, sudo, ntpdate, adduser, apt-transport-https
96+Depends: python-twisted-core, python-twisted-web, debootstrap, dpkg-dev, linux32, file, bzip2, sudo, ntpdate, adduser, apt-transport-https
97 Description: Launchpad buildd slave
98 This is the launchpad buildd slave package. It contains everything needed to
99 get a launchpad buildd going apart from the database manipulation required to
100
101=== modified file 'lib/canonical/config/__init__.py'
102--- lib/canonical/config/__init__.py 2010-01-14 16:39:18 +0000
103+++ lib/canonical/config/__init__.py 2010-04-05 12:47:32 +0000
104@@ -374,13 +374,13 @@
105 _db_config_attrs = frozenset([
106 'dbuser', 'auth_dbuser',
107 'rw_main_master', 'rw_main_slave',
108- 'ro_main_master', 'ro_main_slave', 'auth_master', 'auth_slave',
109+ 'ro_main_master', 'ro_main_slave',
110 'db_statement_timeout', 'db_statement_timeout_precision',
111 'isolation_level', 'randomise_select_results',
112 'soft_request_timeout', 'storm_cache', 'storm_cache_size'])
113 _db_config_required_attrs = frozenset([
114 'dbuser', 'rw_main_master', 'rw_main_slave', 'ro_main_master',
115- 'ro_main_slave', 'auth_master', 'auth_slave'])
116+ 'ro_main_slave'])
117
118 @property
119 def main_master(self):
120
121=== modified file 'lib/canonical/config/schema-lazr.conf'
122--- lib/canonical/config/schema-lazr.conf 2010-03-24 02:37:55 +0000
123+++ lib/canonical/config/schema-lazr.conf 2010-04-05 12:47:32 +0000
124@@ -559,8 +559,6 @@
125 rw_main_slave: dbname=launchpad_prod_2 host=chokecherry.canonical.com
126 ro_main_master: dbname=launchpad_standalone_1 host=chokecherry.canonical.com
127 ro_main_slave: dbname=launchpad_standalone_1 host=chokecherry.canonical.com
128-auth_master: dbname=launchpad_prod_3 host=wildcherry.canonical.com
129-auth_slave: dbname=launchpad_prod_2 host=chokecherry.canonical.com
130
131 # If the replication lag is more than this many seconds, slave databases
132 # will not be used.
133@@ -867,16 +865,10 @@
134 # datatype: integer
135 max_scaling: 500
136
137-[sso]
138-dbuser: sso_main
139-auth_dbuser: sso_auth
140-
141-
142 [launchpad]
143 # The database user which will be used by this process.
144 # datatype: string
145 dbuser: launchpad_main
146-auth_dbuser: launchpad_auth
147 storm_cache: generational
148 storm_cache_size: 10000
149
150
151=== modified file 'lib/canonical/configure.zcml'
152--- lib/canonical/configure.zcml 2010-01-08 21:23:15 +0000
153+++ lib/canonical/configure.zcml 2010-04-05 12:47:32 +0000
154@@ -154,7 +154,5 @@
155 <include package="canonical.lazr" />
156 <include zcml:condition="installed canonical.shipit"
157 package="canonical.shipit" />
158- <include zcml:condition="installed canonical.signon"
159- package="canonical.signon" />
160
161 </configure>
162
163=== modified file 'lib/canonical/database/harness.py'
164--- lib/canonical/database/harness.py 2009-11-05 03:52:51 +0000
165+++ lib/canonical/database/harness.py 2010-04-05 12:47:32 +0000
166@@ -48,8 +48,7 @@
167 from storm.locals import *
168 from storm.expr import *
169 from canonical.launchpad.webapp.interfaces import (
170- IStoreSelector, MAIN_STORE, AUTH_STORE, MASTER_FLAVOR,
171- SLAVE_FLAVOR, DEFAULT_FLAVOR)
172+ IStoreSelector, MAIN_STORE, MASTER_FLAVOR, SLAVE_FLAVOR, DEFAULT_FLAVOR)
173
174
175 def switch_db_user(dbuser, commit_first=True):
176
177=== modified file 'lib/canonical/database/sqlbase.py'
178--- lib/canonical/database/sqlbase.py 2010-03-23 15:04:41 +0000
179+++ lib/canonical/database/sqlbase.py 2010-04-05 12:47:32 +0000
180@@ -271,7 +271,6 @@
181 # This is only used by scripts, so we must connect to the read-write
182 # DB here -- that's why we use rw_main_master directly.
183 main_connection_string = dbconfig.rw_main_master
184- auth_connection_string = dbconfig.auth_master
185
186 # Override dbname and dbhost in the connection string if they
187 # have been passed in.
188@@ -290,7 +289,7 @@
189 match = re.search(r'host=(\S*)', main_connection_string)
190 if match is not None:
191 dbhost = match.group(1)
192- return main_connection_string, auth_connection_string, dbname, dbhost
193+ return main_connection_string, dbname, dbhost
194
195 @classmethod
196 def initZopeless(cls, dbname=None, dbhost=None, dbuser=None,
197@@ -298,7 +297,7 @@
198 # Connect to the auth master store as well, as some scripts might need
199 # to create EmailAddresses and Accounts.
200
201- main_connection_string, auth_connection_string, dbname, dbhost = (
202+ main_connection_string, dbname, dbhost = (
203 cls._get_zopeless_connection_config(dbname, dbhost))
204
205 assert dbuser is not None, '''
206@@ -315,7 +314,6 @@
207 overlay = dedent("""\
208 [database]
209 rw_main_master: %(main_connection_string)s
210- auth_master: %(auth_connection_string)s
211 isolation_level: %(isolation_level)s
212 """ % vars())
213
214
215=== modified file 'lib/canonical/database/tests/test_zopeless_transaction_manager.py'
216--- lib/canonical/database/tests/test_zopeless_transaction_manager.py 2009-12-14 17:38:34 +0000
217+++ lib/canonical/database/tests/test_zopeless_transaction_manager.py 2010-04-05 12:47:32 +0000
218@@ -1,48 +1,17 @@
219 # Copyright 2009 Canonical Ltd. This software is licensed under the
220 # GNU Affero General Public License version 3 (see the file LICENSE).
221
222-from textwrap import dedent
223 import unittest
224
225 from zope.component import getUtility
226
227 from storm.zope.interfaces import IZStorm
228
229-from canonical.config import config
230 from canonical.database.sqlbase import ZopelessTransactionManager
231 from canonical.testing.layers import LaunchpadZopelessLayer
232 from lp.testing import TestCase
233
234
235-class TestZopelessTransactionManagerNoLayer(TestCase):
236-
237- def test_initZopeless_connects_to_auth_master_db(self):
238- # Some scripts might create EmailAddress and Account entries, so
239- # initZopeless has to connect to the auth master db. This is a
240- # bugfix test. The error that this test detects is that the
241- # script used to use the main_master database for the
242- # auth_master. In this test, we make sure that the auth_master
243- # and main_master have different values in the config, and then
244- # show that they are honored. Prior to the fix, ``auth_master``
245- # would have been changed to the same value as ``main_master``.
246- # Now we set up our test data and push it on the config.
247- auth_master = "dbname=example_launchpad_auth_does_not_exist"
248- overlay = dedent("""
249- [database]
250- main_master: dbname=launchpad_dev
251- auth_master: %s
252- """ % (auth_master,))
253- config.push('new-db', overlay)
254- try:
255- main_connection_string, auth_connection_string, dbname, dbhost = (
256- ZopelessTransactionManager._get_zopeless_connection_config(
257- None, None))
258- self.assertEqual(auth_connection_string, auth_master)
259- finally:
260- # Clean up the configuration
261- config.pop('new-db')
262-
263-
264 class TestZopelessTransactionManager(TestCase):
265 layer = LaunchpadZopelessLayer
266
267
268=== modified file 'lib/canonical/launchpad/database/tests/test_oauth.py'
269--- lib/canonical/launchpad/database/tests/test_oauth.py 2009-06-25 05:30:52 +0000
270+++ lib/canonical/launchpad/database/tests/test_oauth.py 2010-04-05 12:47:32 +0000
271@@ -22,7 +22,7 @@
272 """Base tests for the OAuth database classes."""
273 layer = DatabaseFunctionalLayer
274
275- def test__get_store_should_return_the_auth_master_store(self):
276+ def test__get_store_should_return_the_main_master_store(self):
277 """We want all OAuth classes to use the master store.
278 Otherwise, the OAuth exchanges will fail because the authorize
279 screen won't probably find the new request token on the slave store.
280
281=== modified file 'lib/canonical/launchpad/doc/account.txt'
282--- lib/canonical/launchpad/doc/account.txt 2010-02-12 15:57:27 +0000
283+++ lib/canonical/launchpad/doc/account.txt 2010-04-05 12:47:32 +0000
284@@ -196,32 +196,6 @@
285 >>> account.status = AccountStatus.ACTIVE
286 >>> login('no-priv@canonical.com')
287
288-The Account's displayname is synced to the Person's displayname if there
289-is one. If the Person.displayname is changed, the Account.displayname is
290-changed too.
291-
292- >>> from canonical.launchpad.interfaces import IPersonSet
293-
294- >>> personset = getUtility(IPersonSet)
295- >>> person = personset.getByEmail('no-priv@canonical.com')
296- >>> person.displayname = 'Something New'
297- >>> print account.displayname
298- Something New
299-
300-However, the reverse is not true. If we change the Account.displayname,
301-the linked Person.displayname (if there is one) is not updated
302-immediately. Instead, a cron job will sync this information later. This
303-allows displayname changes to happen even when the Person table is
304-unavailable.
305-
306- >>> account.displayname = 'No Privileges Account'
307- >>> print person.displayname
308- Something New
309-
310- >>> person.displayname = 'No Privileges Person'
311- >>> print account.displayname
312- No Privileges Person
313-
314 An Account has an OpenID identifier used to generate the OpenID identity
315 URL.
316
317@@ -242,6 +216,7 @@
318 >>> login('admin@canonical.com')
319 >>> passwordless_account = account_set.new(
320 ... AccountCreationRationale.USER_CREATED, 'Passwordless')
321+ >>> transaction.commit()
322 >>> print passwordless_account.creation_rationale.name
323 USER_CREATED
324 >>> print passwordless_account.displayname
325
326=== modified file 'lib/canonical/launchpad/doc/storm.txt'
327--- lib/canonical/launchpad/doc/storm.txt 2010-02-22 10:33:10 +0000
328+++ lib/canonical/launchpad/doc/storm.txt 2010-04-05 12:47:32 +0000
329@@ -7,10 +7,11 @@
330 specific Storm tools to cope with our master and slave store arrangement.
331
332 >>> from canonical.launchpad.interfaces import (
333- ... EmailAddressStatus, IAccountSet, IEmailAddressSet,
334+ ... EmailAddressStatus, IEmailAddressSet,
335 ... IMasterObject, IMasterStore, ISlaveStore, IStore)
336 >>> from canonical.launchpad.database import (
337 ... Account, AccountPassword, EmailAddress)
338+ >>> from lp.registry.interfaces.person import IPersonSet
339 >>> from lp.registry.model.person import Person
340 >>> from zope.security.proxy import ProxyFactory
341
342@@ -19,30 +20,14 @@
343 a Launchpad database object. You can use adapters to
344 retrieve the correct Store.
345
346- >>> auth_master = IMasterStore(Account)
347 >>> main_master = IMasterStore(Person)
348- >>> auth_master is main_master
349- False
350-
351-
352-You can read most tables from any Store, which is required for doing
353-fast joins in the database. However, when it is not necessary to
354-retrieve objects from the same store as another object, it is better to
355-explicitly use the explicit Store for its replication set. Some tables
356-are only available from this store, such as the AccountPassword table.
357-
358- >>> auth_slave = ISlaveStore(AccountPassword)
359- >>> main_slave = ISlaveStore(Person)
360- >>> auth_slave is main_slave
361- False
362-
363
364 You can detect if a store is writable by checking what interfaces it
365 provides.
366
367- >>> IMasterStore.providedBy(auth_master)
368+ >>> IMasterStore.providedBy(main_master)
369 True
370- >>> ISlaveStore.providedBy(auth_master)
371+ >>> ISlaveStore.providedBy(main_master)
372 False
373
374
375@@ -53,7 +38,6 @@
376 Otherwise, it gives you the master. See IStoreSelector for details.
377
378 >>> main_default = IStore(Person)
379- >>> main_master = IMasterStore(Person)
380 >>> main_slave = ISlaveStore(Person)
381 >>> main_default is main_master
382 True
383@@ -78,11 +62,10 @@
384 changes to an object, just in case you have been passed an instance
385 from a store other than the correct Master.
386
387- >>> auth_slave = ISlaveStore(Account)
388+ >>> main_slave = ISlaveStore(Person)
389 >>> t = transaction.begin()
390- >>> account = auth_slave.find(
391- ... Account, openid_identifier='mark_oid').one()
392- >>> account.displayname = 'Cannot change'
393+ >>> person = main_slave.find(Person, name='mark').one()
394+ >>> person.displayname = 'Cannot change'
395 >>> transaction.commit()
396 Traceback (most recent call last):
397 ...
398@@ -90,9 +73,8 @@
399
400 >>> transaction.abort()
401 >>> t = transaction.begin()
402- >>> account = auth_slave.find(
403- ... Account, openid_identifier='mark_oid').one()
404- >>> IMasterObject(account).displayname = 'Can change'
405+ >>> person = main_slave.find(Person, name='mark').one()
406+ >>> IMasterObject(person).displayname = 'Can change'
407 >>> transaction.commit()
408
409
410@@ -100,61 +82,60 @@
411 similarly wrapped.
412
413 >>> from zope.security.proxy import removeSecurityProxy
414- >>> account = getUtility(IAccountSet).getByEmail('no-priv@canonical.com')
415- >>> removeSecurityProxy(account) is account
416- False
417- >>> account.displayname
418- u'No Privileges Person'
419- >>> account.password
420- Traceback (most recent call last):
421- ...
422- Unauthorized: ...
423-
424- >>> account = IMasterObject(account)
425- >>> removeSecurityProxy(account) is account
426- False
427- >>> account.displayname
428- u'No Privileges Person'
429- >>> account.password
430- Traceback (most recent call last):
431- ...
432- Unauthorized: ...
433-
434- >>> account = IMasterObject(removeSecurityProxy(account))
435- >>> removeSecurityProxy(account) is account
436+ >>> person = getUtility(IPersonSet).getByEmail('no-priv@canonical.com')
437+ >>> removeSecurityProxy(person) is person
438+ False
439+ >>> person.displayname
440+ u'No Privileges Person'
441+ >>> person.name = 'foo'
442+ Traceback (most recent call last):
443+ ...
444+ Unauthorized: ...
445+
446+ >>> person = IMasterObject(person)
447+ >>> removeSecurityProxy(person) is person
448+ False
449+ >>> person.displayname
450+ u'No Privileges Person'
451+ >>> person.name = 'foo'
452+ Traceback (most recent call last):
453+ ...
454+ Unauthorized: ...
455+
456+ >>> person = IMasterObject(removeSecurityProxy(person))
457+ >>> removeSecurityProxy(person) is person
458 True
459- >>> account.displayname
460+ >>> person.displayname
461 u'No Privileges Person'
462- >>> account.password
463- u'...'
464+ >>> person.name = 'foo'
465
466 Our objects may compare equal even if they have come from different
467 stores.
468
469- >>> auth_master_email = IMasterStore(EmailAddress).find(
470- ... EmailAddress, Person.name == 'janitor',
471- ... EmailAddress.person==Person.id).one()
472- >>> auth_slave_email = ISlaveStore(EmailAddress).find(
473- ... EmailAddress, Person.name == 'janitor',
474- ... EmailAddress.person==Person.id).one()
475- >>> auth_master_email is auth_slave_email
476+ >>> master_email = IMasterStore(EmailAddress).find(
477+ ... EmailAddress, Person.name == 'janitor',
478+ ... EmailAddress.person==Person.id).one()
479+ >>> slave_email = ISlaveStore(EmailAddress).find(
480+ ... EmailAddress, Person.name == 'janitor',
481+ ... EmailAddress.person==Person.id).one()
482+ >>> master_email is slave_email
483 False
484- >>> auth_master_email == auth_slave_email
485+ >>> master_email == slave_email
486 True
487- >>> auth_master_email != auth_slave_email
488+ >>> master_email != slave_email
489 False
490
491 Comparison works for security wrapped objects too.
492
493 >>> wrapped_email = getUtility(IEmailAddressSet).getByEmail(
494- ... auth_master_email.email)
495- >>> removeSecurityProxy(wrapped_email) is auth_master_email
496+ ... master_email.email)
497+ >>> removeSecurityProxy(wrapped_email) is master_email
498 True
499- >>> wrapped_email is auth_master_email
500+ >>> wrapped_email is master_email
501 False
502- >>> wrapped_email == auth_master_email
503+ >>> wrapped_email == master_email
504 True
505- >>> wrapped_email != auth_master_email
506+ >>> wrapped_email != master_email
507 False
508
509 Objects not yet flushed to the database also compare equal.
510@@ -176,10 +157,9 @@
511
512 Objects differing by class never compare equal.
513
514- >>> account_one = IMasterStore(Account).get(Account, 1)
515- >>> person_one = IMasterStore(Account).get(Person, 1)
516- >>> account_one == person_one
517+ >>> email_one = IMasterStore(EmailAddress).get(EmailAddress, 1)
518+ >>> person_one = IMasterStore(Person).get(Person, 1)
519+ >>> email_one == person_one
520 False
521- >>> account_one != person_one
522+ >>> email_one != person_one
523 True
524-
525
526=== modified file 'lib/canonical/launchpad/pagetests/standalone/xx-opstats.txt'
527--- lib/canonical/launchpad/pagetests/standalone/xx-opstats.txt 2010-01-13 13:50:39 +0000
528+++ lib/canonical/launchpad/pagetests/standalone/xx-opstats.txt 2010-04-05 12:47:32 +0000
529@@ -236,8 +236,6 @@
530 ... [database]
531 ... rw_main_master: dbname=nonexistant
532 ... rw_main_slave: dbname=nonexistant
533- ... auth_master: dbname=nonexistant
534- ... auth_slave: dbname=nonexistant
535 ...
536 ... [launchpad_session]
537 ... dbname: nonexistant
538
539=== modified file 'lib/canonical/launchpad/scripts/garbo.py'
540--- lib/canonical/launchpad/scripts/garbo.py 2010-03-26 14:33:46 +0000
541+++ lib/canonical/launchpad/scripts/garbo.py 2010-04-05 12:47:32 +0000
542@@ -29,7 +29,7 @@
543 from canonical.launchpad.utilities.looptuner import (
544 DBLoopTuner, TunableLoop)
545 from canonical.launchpad.webapp.interfaces import (
546- IStoreSelector, AUTH_STORE, MAIN_STORE, MASTER_FLAVOR)
547+ IStoreSelector, MAIN_STORE, MASTER_FLAVOR)
548 from lp.bugs.interfaces.bug import IBugSet
549 from lp.bugs.interfaces.bugjob import ICalculateBugHeatJobSource
550 from lp.bugs.model.bugnotification import BugNotification
551@@ -121,19 +121,17 @@
552 transaction.commit()
553
554
555-class OpenIDAssociationPruner(TunableLoop):
556+class OpenIDConsumerAssociationPruner(TunableLoop):
557 minimum_chunk_size = 3500
558 maximum_chunk_size = 50000
559
560- table_name = 'OpenIDAssociation'
561- store_name = AUTH_STORE
562+ table_name = 'OpenIDConsumerAssociation'
563
564 _num_removed = None
565
566 def __init__(self, log, abort_time=None):
567- super(OpenIDAssociationPruner, self).__init__(log, abort_time)
568- self.store = getUtility(IStoreSelector).get(
569- self.store_name, MASTER_FLAVOR)
570+ super(OpenIDConsumerAssociationPruner, self).__init__(log, abort_time)
571+ self.store = getUtility(IStoreSelector).get(MAIN_STORE, MASTER_FLAVOR)
572
573 def __call__(self, chunksize):
574 result = self.store.execute("""
575@@ -152,11 +150,6 @@
576 return self._num_removed == 0
577
578
579-class OpenIDConsumerAssociationPruner(OpenIDAssociationPruner):
580- table_name = 'OpenIDConsumerAssociation'
581- store_name = MAIN_STORE
582-
583-
584 class RevisionCachePruner(TunableLoop):
585 """A tunable loop to remove old revisions from the cache."""
586
587@@ -869,7 +862,6 @@
588 tunable_loops = [
589 OAuthNoncePruner,
590 OpenIDConsumerNoncePruner,
591- OpenIDAssociationPruner,
592 OpenIDConsumerAssociationPruner,
593 RevisionCachePruner,
594 BugHeatUpdater,
595
596=== modified file 'lib/canonical/launchpad/scripts/tests/test_garbo.py'
597--- lib/canonical/launchpad/scripts/tests/test_garbo.py 2010-01-22 06:03:19 +0000
598+++ lib/canonical/launchpad/scripts/tests/test_garbo.py 2010-04-05 12:47:32 +0000
599@@ -29,11 +29,11 @@
600 from lp.testing import TestCase, TestCaseWithFactory
601 from canonical.launchpad.scripts.garbo import (
602 DailyDatabaseGarbageCollector, HourlyDatabaseGarbageCollector,
603- OpenIDAssociationPruner, OpenIDConsumerAssociationPruner)
604+ OpenIDConsumerAssociationPruner)
605 from canonical.launchpad.scripts.tests import run_script
606 from canonical.launchpad.scripts.logger import QuietFakeLogger
607 from canonical.launchpad.webapp.interfaces import (
608- IStoreSelector, MASTER_FLAVOR)
609+ IStoreSelector, MAIN_STORE, MASTER_FLAVOR)
610 from canonical.testing.layers import (
611 DatabaseLayer, LaunchpadScriptLayer, LaunchpadZopelessLayer)
612 from lp.bugs.model.bugnotification import (
613@@ -219,12 +219,12 @@
614 Min(CodeImportResult.date_created)).one().replace(tzinfo=UTC)
615 >= now - timedelta(days=30))
616
617- def test_OpenIDAssociationPruner(self, pruner=OpenIDAssociationPruner):
618- store_name = pruner.store_name
619+ def test_OpenIDConsumerAssociationPruner(self):
620+ pruner = OpenIDConsumerAssociationPruner
621 table_name = pruner.table_name
622 LaunchpadZopelessLayer.switchDbUser('testadmin')
623 store_selector = getUtility(IStoreSelector)
624- store = store_selector.get(store_name, MASTER_FLAVOR)
625+ store = store_selector.get(MAIN_STORE, MASTER_FLAVOR)
626 now = time.time()
627 # Create some associations in the past with lifetimes
628 for delta in range(0, 20):
629@@ -247,7 +247,7 @@
630 self.runHourly()
631
632 LaunchpadZopelessLayer.switchDbUser('testadmin')
633- store = store_selector.get(store_name, MASTER_FLAVOR)
634+ store = store_selector.get(MAIN_STORE, MASTER_FLAVOR)
635 # Confirm all the rows we know should have been expired have
636 # been expired. These are the ones that would be expired using
637 # the test start time as 'now'.
638@@ -263,9 +263,6 @@
639 "SELECT COUNT(*) FROM %s" % table_name).get_one()[0]
640 self.failUnless(num_unexpired > 0)
641
642- def test_OpenIDConsumerAssociationPruner(self):
643- self.test_OpenIDAssociationPruner(OpenIDConsumerAssociationPruner)
644-
645 def test_RevisionAuthorEmailLinker(self):
646 LaunchpadZopelessLayer.switchDbUser('testadmin')
647 rev1 = self.factory.makeRevision('Author 1 <author-1@Example.Org>')
648@@ -373,6 +370,7 @@
649
650 # If we remove the email address that was subscribed, the
651 # garbage collector removes the subscription.
652+ LaunchpadZopelessLayer.switchDbUser('testadmin')
653 Store.of(email).remove(email)
654 transaction.commit()
655 self.runDaily()
656
657=== modified file 'lib/canonical/launchpad/webapp/adapter.py'
658--- lib/canonical/launchpad/webapp/adapter.py 2010-03-25 11:58:42 +0000
659+++ lib/canonical/launchpad/webapp/adapter.py 2010-04-05 12:47:32 +0000
660@@ -40,14 +40,13 @@
661 from canonical.launchpad.readonly import is_read_only
662 from canonical.launchpad.webapp.dbpolicy import MasterDatabasePolicy
663 from canonical.launchpad.webapp.interfaces import (
664- AUTH_STORE, DEFAULT_FLAVOR, IStoreSelector,
665- MAIN_STORE, MASTER_FLAVOR, ReadOnlyModeViolation, SLAVE_FLAVOR)
666+ DEFAULT_FLAVOR, IStoreSelector, MAIN_STORE, MASTER_FLAVOR,
667+ ReadOnlyModeViolation, SLAVE_FLAVOR)
668 from canonical.launchpad.webapp.opstats import OpStats
669 from canonical.lazr.utils import safe_hasattr
670
671
672 __all__ = [
673- 'DisconnectionError',
674 'RequestExpired',
675 'set_request_started',
676 'clear_request_started',
677@@ -327,7 +326,7 @@
678
679 def __init__(self, uri):
680 # The uri is just a property name in the config, such as main_master
681- # or auth_slave.
682+ # or main_slave.
683 # We don't invoke the superclass constructor as it has a very limited
684 # opinion on what uri is.
685 # pylint: disable-msg=W0231
686@@ -356,7 +355,7 @@
687 'Connection uri %s does not match section-realm-flavor format'
688 % repr(self._uri.database))
689
690- assert realm in ('main', 'auth'), 'Unknown realm %s' % realm
691+ assert realm == 'main', 'Unknown realm %s' % realm
692 assert flavor in ('master', 'slave'), 'Unknown flavor %s' % flavor
693
694 my_dbconfig = DatabaseConfig()
695@@ -572,14 +571,6 @@
696 return db_policy.getStore(name, flavor)
697
698
699-# There are not many tables outside of the main replication set, so we
700-# can just maintain a hardcoded list of what isn't in there for now.
701-_auth_store_tables = frozenset([
702- 'Account', 'AccountPassword', 'AuthToken', 'EmailAddress',
703- 'OpenIDAssociation', 'OpenIDAuthorization', 'OpenIDNonce',
704- 'OpenIDRPSummary'])
705-
706-
707 # We want to be able to adapt a Storm class to an IStore, IMasterStore or
708 # ISlaveStore. Unfortunately, the component architecture provides no
709 # way for us to declare that a class, and all its subclasses, provides
710@@ -588,9 +579,7 @@
711 def get_store(storm_class, flavor=DEFAULT_FLAVOR):
712 """Return a flavored Store for the given database class."""
713 table = getattr(removeSecurityProxy(storm_class), '__storm_table__', None)
714- if table in _auth_store_tables:
715- return getUtility(IStoreSelector).get(AUTH_STORE, flavor)
716- elif table is not None:
717+ if table is not None:
718 return getUtility(IStoreSelector).get(MAIN_STORE, flavor)
719 else:
720 return None
721
722=== modified file 'lib/canonical/launchpad/webapp/ftests/test_adapter_permissions.txt'
723--- lib/canonical/launchpad/webapp/ftests/test_adapter_permissions.txt 2009-06-11 01:28:55 +0000
724+++ lib/canonical/launchpad/webapp/ftests/test_adapter_permissions.txt 2010-04-05 12:47:32 +0000
725@@ -10,8 +10,7 @@
726
727 >>> from lp.registry.model.person import Person
728 >>> from canonical.launchpad.webapp.interfaces import (
729- ... IStoreSelector, AUTH_STORE, MAIN_STORE,
730- ... MASTER_FLAVOR, SLAVE_FLAVOR)
731+ ... IStoreSelector, MAIN_STORE, MASTER_FLAVOR, SLAVE_FLAVOR)
732 >>> import transaction
733 >>> from zope.component import getUtility
734
735@@ -47,25 +46,3 @@
736 >>> main_master.find(Person, name='janitor').one().displayname
737 u'BenD'
738 >>> transaction.abort()
739-
740-
741-A MASTER_FLAVOR Store does not allow writes to tables outside of that
742-Store's replication set.
743-
744- >>> t = transaction.begin()
745- >>> person = main_master.find(Person, name='no-priv').one()
746- >>> account = person.account
747- >>> account.displayname = "Ben Dover"
748- >>> main_master.flush()
749- Traceback (most recent call last):
750- ...
751- ProgrammingError: permission denied for relation account
752- >>> transaction.abort()
753-
754- >>> t = transaction.begin()
755- >>> auth_master = getUtility(IStoreSelector).get(AUTH_STORE, MASTER_FLAVOR)
756- >>> person = auth_master.find(Person, name='no-priv').one()
757- >>> account = person.account
758- >>> account.displayname = "Ben Dover"
759- >>> auth_master.flush()
760- >>> transaction.abort()
761
762=== modified file 'lib/canonical/launchpad/webapp/interfaces.py'
763--- lib/canonical/launchpad/webapp/interfaces.py 2010-03-26 22:57:38 +0000
764+++ lib/canonical/launchpad/webapp/interfaces.py 2010-04-05 12:47:32 +0000
765@@ -745,9 +745,7 @@
766 #
767
768 MAIN_STORE = 'main' # The main database.
769-AUTH_STORE = 'auth' # The authentication database.
770-
771-ALL_STORES = frozenset([MAIN_STORE, AUTH_STORE])
772+ALL_STORES = frozenset([MAIN_STORE])
773
774 DEFAULT_FLAVOR = 'default' # Default flavor for current state.
775 MASTER_FLAVOR = 'master' # The master database.
776
777=== modified file 'lib/canonical/launchpad/webapp/tests/test_dbpolicy.py'
778--- lib/canonical/launchpad/webapp/tests/test_dbpolicy.py 2010-02-24 23:18:40 +0000
779+++ lib/canonical/launchpad/webapp/tests/test_dbpolicy.py 2010-04-05 12:47:32 +0000
780@@ -25,7 +25,7 @@
781 ReadOnlyLaunchpadDatabasePolicy, SlaveDatabasePolicy,
782 SlaveOnlyDatabasePolicy)
783 from canonical.launchpad.webapp.interfaces import (
784- ALL_STORES, AUTH_STORE, DEFAULT_FLAVOR, DisallowedStore, IDatabasePolicy,
785+ ALL_STORES, DEFAULT_FLAVOR, DisallowedStore, IDatabasePolicy,
786 IStoreSelector, MAIN_STORE, MASTER_FLAVOR, ReadOnlyModeDisallowedStore,
787 SLAVE_FLAVOR)
788 from canonical.launchpad.webapp.servers import LaunchpadTestRequest
789@@ -47,9 +47,6 @@
790 main_store = store_selector.get(MAIN_STORE, DEFAULT_FLAVOR)
791 self.failUnlessEqual(self.getDBUser(main_store), 'launchpad_main')
792
793- auth_store = store_selector.get(AUTH_STORE, DEFAULT_FLAVOR)
794- self.failUnlessEqual(self.getDBUser(auth_store), 'launchpad_auth')
795-
796 def getDBUser(self, store):
797 return store.execute(
798 'SHOW session_authorization').get_one()[0]
799
800=== removed symlink 'lib/canonical/signon'
801=== target was u'../../sourcecode/canonical-identity-provider'
802=== modified file 'lib/lp/bugs/doc/checkwatches.txt'
803--- lib/lp/bugs/doc/checkwatches.txt 2010-03-26 15:24:59 +0000
804+++ lib/lp/bugs/doc/checkwatches.txt 2010-04-05 12:47:32 +0000
805@@ -337,9 +337,13 @@
806 If a bug tracker doesn't have any watches to update, forceUpdateAll()
807 will ignore it.
808
809+ >>> transaction.commit()
810+ >>> LaunchpadZopelessLayer.switchDbUser('launchpad')
811 >>> login('test@canonical.com')
812 >>> empty_tracker = factory.makeBugTracker(
813 ... 'http://example.com', BugTrackerType.ROUNDUP)
814+ >>> transaction.commit()
815+ >>> LaunchpadZopelessLayer.switchDbUser(config.checkwatches.dbuser)
816 >>> empty_tracker_name = empty_tracker.name
817 >>> update_all(empty_tracker_name)
818 INFO Bug tracker 'auto-example.com' doesn't have any watches. Ignoring.
819
820=== modified file 'lib/lp/bugs/doc/externalbugtracker-comment-imports.txt'
821--- lib/lp/bugs/doc/externalbugtracker-comment-imports.txt 2010-03-25 14:28:33 +0000
822+++ lib/lp/bugs/doc/externalbugtracker-comment-imports.txt 2010-04-05 12:47:32 +0000
823@@ -373,8 +373,10 @@
824 since they aren't a valid Launchpad user, having been created during the
825 import process.
826
827-We'll add a listener to check for Karma events.
828+We'll create a bug watch and add a listener to check for Karma events.
829
830+ >>> LaunchpadZopelessLayer.switchDbUser('launchpad')
831+ >>> bug_watch = factory.makeBugWatch('123456')
832 >>> from lp.registry.tests.karma import KarmaAssignedEventListener
833 >>> karma_helper = KarmaAssignedEventListener()
834 >>> karma_helper.register_listener()
835@@ -382,8 +384,6 @@
836 Importing a comment with a CVE reference will produce a CVE link in
837 Launchpad but will result in no Karma records being created.
838
839- >>> LaunchpadZopelessLayer.switchDbUser('launchpad')
840- >>> bug_watch = factory.makeBugWatch('123456')
841 >>> transaction.commit()
842 >>> LaunchpadZopelessLayer.switchDbUser(config.checkwatches.dbuser)
843 >>> external_bugtracker.remote_comments = {
844
845=== modified file 'lib/lp/code/doc/branch-karma.txt'
846--- lib/lp/code/doc/branch-karma.txt 2010-02-16 20:36:48 +0000
847+++ lib/lp/code/doc/branch-karma.txt 2010-04-05 12:47:32 +0000
848@@ -49,6 +49,7 @@
849 You get karma for linking a bug to a branch.
850
851 >>> bug = factory.makeBug(product=fooix)
852+ Karma added: action=bugcreated, product=fooix, person=person-name11
853 >>> branch_link = bug.linkBranch(branch, eric)
854 Karma added: action=bugbranchcreated, product=fooix, person=eric
855
856
857=== modified file 'lib/lp/registry/model/person.py'
858--- lib/lp/registry/model/person.py 2010-03-24 23:19:52 +0000
859+++ lib/lp/registry/model/person.py 2010-04-05 12:47:32 +0000
860@@ -124,7 +124,7 @@
861 TeamMembershipStatus)
862 from lp.registry.interfaces.wikiname import IWikiName, IWikiNameSet
863 from canonical.launchpad.webapp.interfaces import (
864- AUTH_STORE, ILaunchBag, IStoreSelector, MASTER_FLAVOR)
865+ ILaunchBag, IStoreSelector, MASTER_FLAVOR)
866
867 from lp.soyuz.model.archive import Archive
868 from lp.registry.model.codeofconduct import SignedCodeOfConduct
869@@ -263,22 +263,7 @@
870 return '<Person at 0x%x %s (%s)>' % (
871 id(self), self.name, self.displayname)
872
873- def _sync_displayname(self, attr, value):
874- """Update any related Account.displayname.
875-
876- We can't do this in a DB trigger as soon the Account table will
877- in a separate database to the Person table.
878- """
879- if self.accountID is not None:
880- auth_store = getUtility(IStoreSelector).get(
881- AUTH_STORE, MASTER_FLAVOR)
882- account = auth_store.get(Account, self.accountID)
883- if account.displayname != value:
884- account.displayname = value
885- return value
886-
887- displayname = StringCol(dbName='displayname', notNull=True,
888- storm_validator=_sync_displayname)
889+ displayname = StringCol(dbName='displayname', notNull=True)
890
891 teamdescription = StringCol(dbName='teamdescription', default=None)
892 homepage_content = StringCol(default=None)
893
894=== modified file 'lib/lp/registry/stories/person/xx-admin-person-review.txt'
895--- lib/lp/registry/stories/person/xx-admin-person-review.txt 2010-01-30 22:39:54 +0000
896+++ lib/lp/registry/stories/person/xx-admin-person-review.txt 2010-04-05 12:47:32 +0000
897@@ -63,7 +63,7 @@
898 >>> print admin_browser.title
899 The one and only Salgado does not use Launchpad
900 >>> print get_feedback_messages(admin_browser.contents)[0]
901- The account "The one and only Salgado" has been suspended.
902+ The account "Guilherme Salgado" has been suspended.
903
904 The admin can see the account information of a user that does not use
905 Launchpad, and can change the account too. Note that all pages that belong
906
907=== modified file 'lib/lp/registry/tests/test_personset.py'
908--- lib/lp/registry/tests/test_personset.py 2010-03-11 20:54:36 +0000
909+++ lib/lp/registry/tests/test_personset.py 2010-04-05 12:47:32 +0000
910@@ -99,23 +99,19 @@
911 # Person in question.
912
913 # Create a testing `Account` and a testing `Person` directly,
914- # linked. However the `Account` email is not linked to the
915- # `Person`.
916+ # linked.
917 testing_account = self.factory.makeAccount(
918 self.displayname, email=self.email_address)
919 testing_person = removeSecurityProxy(
920 testing_account).createPerson(self.rationale)
921- self.assertIs(None, testing_account.preferredemail.person)
922- self.assertIs(None, testing_person.preferredemail)
923+ self.assertEqual(
924+ testing_person, testing_account.preferredemail.person)
925
926+ # Since there's an existing Person for the given email address,
927+ # IPersonSet.ensurePerson() will just return it.
928 ensured_person = self.person_set.ensurePerson(
929 self.email_address, self.displayname, self.rationale)
930-
931- # The existing Person was retrieved and the Account
932- # 'preferredemail' is also bound to the existing Person.
933- self.assertEquals(testing_person.id, ensured_person.id)
934- self.assertEquals(testing_account.preferredemail.id,
935- ensured_person.preferredemail.id)
936+ self.assertEqual(testing_person, ensured_person)
937
938
939 class TestPersonSetMerge(TestCaseWithFactory):
940
941=== modified file 'lib/lp/testopenid/browser/server.py'
942--- lib/lp/testopenid/browser/server.py 2010-02-24 12:52:08 +0000
943+++ lib/lp/testopenid/browser/server.py 2010-04-05 12:47:32 +0000
944@@ -6,7 +6,7 @@
945 __all__ = [
946 'PersistentIdentityView',
947 'TestOpenIDApplicationNavigation',
948- 'TestOpenIDIndexView'
949+ 'TestOpenIDIndexView',
950 'TestOpenIDLoginView',
951 'TestOpenIDRootUrlData',
952 'TestOpenIDView',
953@@ -21,6 +21,7 @@
954 from zope.security.proxy import isinstance as zisinstance
955 from zope.session.interfaces import ISession
956
957+from openid import oidutil
958 from openid.server.server import CheckIDRequest, Server
959 from openid.store.memstore import MemoryStore
960
961@@ -47,6 +48,10 @@
962 openid_store = MemoryStore()
963
964
965+# Shut up noisy OpenID library
966+oidutil.log = lambda message, level=0: None
967+
968+
969 class TestOpenIDRootUrlData:
970 """`ICanonicalUrlData` for the test OpenID provider."""
971
972
973=== modified file 'utilities/sourcedeps.conf'
974--- utilities/sourcedeps.conf 2010-03-26 17:53:41 +0000
975+++ utilities/sourcedeps.conf 2010-04-05 12:47:32 +0000
976@@ -15,5 +15,4 @@
977 subunit lp:~launchpad-pqm/subunit/trunk;revno=61
978 subvertpy lp:~launchpad-pqm/subvertpy/trunk;revno=2040
979 testresources lp:~launchpad-pqm/testresources/dev;revno=16
980-canonical-identity-provider lp:~launchpad-pqm/canonical-identity-provider/trunk;revno=8903 optional
981 shipit lp:~launchpad-pqm/shipit/trunk;revno=8903 optional

Subscribers

People subscribed via source and target branches

to status/vote changes: