Merge lp:~zulcss/keystone/keystone-cloud-g2 into lp:~ubuntu-cloud-archive/ubuntu/precise/keystone/trunk

Proposed by Chuck Short
Status: Merged
Approved by: Adam Gandelman
Approved revision: 38
Merged at revision: 38
Proposed branch: lp:~zulcss/keystone/keystone-cloud-g2
Merge into: lp:~ubuntu-cloud-archive/ubuntu/precise/keystone/trunk
Diff against target: 14128 lines (+7542/-3798)
123 files modified
AUTHORS (+7/-0)
ChangeLog (+1002/-0)
HACKING.rst (+1/-1)
MANIFEST.in (+1/-1)
README.rst (+7/-0)
bin/keystone-all (+8/-1)
debian/changelog (+33/-0)
debian/control (+5/-5)
debian/keystone.config (+0/-19)
debian/keystone.manpages (+1/-1)
debian/keystone.postinst (+3/-25)
debian/keystone.postrm (+0/-14)
debian/keystone.prerm (+0/-17)
debian/keystone.templates (+1/-1)
debian/keystone.upstart (+4/-2)
debian/man/keystone-admin.8 (+0/-63)
debian/man/keystone-auth.8 (+0/-63)
debian/man/keystone-control.8 (+0/-63)
debian/man/keystone-import.8 (+0/-12)
debian/man/keystone.8 (+0/-64)
debian/patches/fix-ubuntu-tests.patch (+38/-3)
debian/po/POTFILES.in (+1/-0)
debian/po/templates.pot (+58/-0)
debian/rules (+1/-1)
debian/tests/test_overrides.conf (+3/-3)
doc/source/configuration.rst (+10/-10)
doc/source/configuringservices.rst (+2/-145)
doc/source/external-auth.rst (+117/-0)
doc/source/index.rst (+1/-0)
doc/source/setup.rst (+1/-1)
keystone.egg-info/SOURCES.txt (+26/-4)
keystone.egg-info/requires.txt (+1/-1)
keystone/catalog/__init__.py (+2/-0)
keystone/catalog/backends/sql.py (+31/-23)
keystone/catalog/backends/templated.py (+1/-1)
keystone/catalog/controllers.py (+184/-0)
keystone/catalog/core.py (+11/-143)
keystone/catalog/routers.py (+25/-0)
keystone/clean.py (+11/-6)
keystone/cli.py (+62/-85)
keystone/common/bufferedhttp.py (+2/-2)
keystone/common/cms.py (+2/-2)
keystone/common/controller.py (+15/-15)
keystone/common/dependency.py (+67/-0)
keystone/common/ldap/core.py (+18/-15)
keystone/common/ldap/fakeldap.py (+28/-26)
keystone/common/models.py (+18/-1)
keystone/common/router.py (+56/-0)
keystone/common/sql/core.py (+2/-1)
keystone/common/sql/legacy.py (+1/-1)
keystone/common/sql/migrate_repo/versions/001_add_initial_tables.py (+8/-2)
keystone/common/sql/migrate_repo/versions/003_sqlite_downgrade.sql (+0/-1)
keystone/common/sql/migrate_repo/versions/003_token_valid.py (+0/-4)
keystone/common/sql/migrate_repo/versions/006_add_policy_table.py (+5/-2)
keystone/common/sql/migrate_repo/versions/007_add_domain_tables.py (+5/-1)
keystone/common/sql/migrate_repo/versions/008_normalize_identity.py (+58/-0)
keystone/common/sql/migrate_repo/versions/008_sqlite_downgrade.sql (+5/-0)
keystone/common/sql/migrate_repo/versions/009_normalize_identity_migration.py (+145/-0)
keystone/common/sql/migrate_repo/versions/010_endpoints_v3.py (+53/-0)
keystone/common/sql/migrate_repo/versions/011_populate_endpoint_type.py (+96/-0)
keystone/common/sql/migrate_repo/versions/012_drop_legacy_endpoints.py (+50/-0)
keystone/common/sql/migrate_repo/versions/013_add_group_tables.py (+93/-0)
keystone/common/sql/migration.py (+1/-1)
keystone/common/sql/nova.py (+7/-7)
keystone/common/utils.py (+34/-11)
keystone/common/wsgi.py (+4/-4)
keystone/config.py (+19/-3)
keystone/contrib/admin_crud/core.py (+5/-6)
keystone/contrib/ec2/core.py (+6/-16)
keystone/contrib/user_crud/core.py (+5/-12)
keystone/controllers.py (+144/-0)
keystone/exception.py (+4/-0)
keystone/identity/__init__.py (+2/-0)
keystone/identity/backends/kvs.py (+192/-15)
keystone/identity/backends/ldap/core.py (+113/-3)
keystone/identity/backends/pam.py (+0/-3)
keystone/identity/backends/sql.py (+317/-61)
keystone/identity/controllers.py (+644/-0)
keystone/identity/core.py (+114/-629)
keystone/identity/routers.py (+179/-0)
keystone/locale/hu/LC_MESSAGES/keystone.po (+313/-0)
keystone/locale/keystone.pot (+279/-9)
keystone/middleware/swift_auth.py (+0/-295)
keystone/openstack/common/cfg.py (+298/-173)
keystone/policy/__init__.py (+2/-0)
keystone/policy/backends/rules.py (+1/-1)
keystone/policy/controllers.py (+48/-0)
keystone/policy/core.py (+3/-33)
keystone/policy/routers.py (+22/-0)
keystone/routers.py (+69/-0)
keystone/service.py (+28/-974)
keystone/test.py (+23/-10)
keystone/token/__init__.py (+2/-0)
keystone/token/backends/kvs.py (+7/-7)
keystone/token/backends/memcache.py (+4/-4)
keystone/token/backends/sql.py (+4/-4)
keystone/token/controllers.py (+606/-0)
keystone/token/core.py (+28/-20)
keystone/token/routers.py (+57/-0)
run_tests.sh (+2/-2)
setup.py (+0/-1)
tests/_ldap_livetest.py (+0/-1)
tests/default_fixtures.py (+8/-0)
tests/test_auth.py (+389/-0)
tests/test_backend.py (+326/-17)
tests/test_backend_ldap.py (+47/-0)
tests/test_backend_sql.py (+34/-46)
tests/test_cert_setup.py (+9/-7)
tests/test_content_types.py (+29/-2)
tests/test_contrib_s3_core.py (+54/-0)
tests/test_drivers.py (+52/-0)
tests/test_import_legacy.py (+5/-3)
tests/test_injection.py (+141/-0)
tests/test_s3_token_middleware.py (+4/-4)
tests/test_service.py (+0/-298)
tests/test_sql_upgrade.py (+236/-12)
tests/test_swift_auth_middleware.py (+0/-249)
tests/test_v3.py (+9/-0)
tests/test_v3_identity.py (+198/-3)
tools/flakes.py (+22/-0)
tools/pip-requires (+1/-1)
tools/test-requires (+2/-0)
tox.ini (+4/-0)
To merge this branch: bzr merge lp:~zulcss/keystone/keystone-cloud-g2
Reviewer Review Type Date Requested Status
Adam Gandelman (community) Needs Fixing
Review via email: mp+144557@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Adam Gandelman (gandelman-a) wrote :

Please maintain the 0ubuntuX versioning (2013.1~g2-0ubuntu1~cloud0)

review: Needs Fixing
38. By Chuck Short

Fix changelog

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'AUTHORS'
2--- AUTHORS 2012-11-23 09:01:53 +0000
3+++ AUTHORS 2013-01-25 16:27:23 +0000
4@@ -40,6 +40,7 @@
5 Doug Hellmann <doug.hellmann@dreamhost.com>
6 Ed Leafe <ed@leafe.com>
7 Édouard Thuleau <edouard1.thuleau@orange.com>
8+Eduardo Patrocinio <epatro@gmail.com>
9 Eoghan Glynn <eglynn@redhat.com>
10 Everett Toews <everett.toews@gmail.com>
11 Ewan Mellor <ewan.mellor@citrix.com>
12@@ -64,6 +65,7 @@
13 Joe Heck <heckj@mac.com>
14 Joe Savak <joe.savak@rackspace.com>
15 Johannes Erdfelt <johannes.erdfelt@rackspace.com>
16+John Bresnahan <jbresnah@redhat.com>
17 John Dickinson <me@not.mn>
18 John Eo <john.eo@rackspace.com>
19 John Eo <joon.eo@gmail.com>
20@@ -85,6 +87,7 @@
21 Lin Hua Cheng <lin-hua.cheng@hp.com>
22 long-wang <long.wang@bj.cs2c.com.cn>
23 Mark Gius <mgius7096@gmail.com>
24+Mark J. Washenberger <mark.washenberger@markwash.net>
25 Mark McLoughlin <markmc@redhat.com>
26 Maru Newby <mnewby@internap.com>
27 Michael Basnight <mbasnight@gmail.com>
28@@ -92,6 +95,7 @@
29 Mohammed Naser <mnaser@vexxhost.com>
30 monsterxx03 <xyj.asmy@gmail.com>
31 Monty Taylor <mordred@inaugust.com>
32+Nachiappan VR N <nachiappan.veerappan-nachiappan@hp.com>
33 OpenStack Jenkins <jenkins@openstack.org>
34 Pádraig Brady <pbrady@redhat.com>
35 Pádraig Brady <P@draigBrady.com>
36@@ -121,11 +125,13 @@
37 Sirish Bitra <sirish.bitra@gmail.com>
38 Sony K. Philip <sony@hcleai.com>
39 Stef T <stelford@internap.com>
40+Steve Martinelli <stevemar@ca.ibm.com>
41 Syed Armani <dce3062@gmail.com>
42 termie <github@anarkystic.com>
43 Thierry Carrez <thierry@openstack.org>
44 Tim Simpson <tim.simpson@rackspace.com>
45 Todd Willey <xtoddx@gmail.com>
46+Tom Fifield <fifieldt@unimelb.edu.au>
47 Unmesh Gurjar <unmesh.gurjar@nttdata.com>
48 Unmesh Gurjar <unmesh.gurjar@vertex.co.in>
49 Vincent Hou <sbhou@cn.ibm.com>
50@@ -134,6 +140,7 @@
51 vishvananda <vishvananda@gmail.com>
52 wanglong <wl3617@qq.com>
53 Will Kelly <the.william.kelly@gmail.com>
54+Wu Wenxiang <wu.wenxiang@99cloud.net>
55 Yaguang Tang <heut2008@gmail.com>
56 Yogeshwar Srikrishnan <yoga80@yahoo.com>
57 Yong Sheng Gong <gongysh@cn.ibm.com>
58
59=== modified file 'ChangeLog'
60--- ChangeLog 2012-11-23 09:01:53 +0000
61+++ ChangeLog 2013-01-25 16:27:23 +0000
62@@ -1,3 +1,1005 @@
63+commit 788f6c5ee60bea0146ae0f86a7aec9430654be8d
64+Merge: 4fae928 3244451
65+Author: Jenkins <jenkins@review.openstack.org>
66+Date: Wed Jan 9 05:38:12 2013 +0000
67+
68+ Merge "Add missing .po files to tarball"
69+
70+commit 4fae928c59beaa558306a5aa3a3aa5c6f4945b70
71+Author: Henry Nash <henryn@linux.vnet.ibm.com>
72+Date: Thu Dec 13 16:48:13 2012 +0000
73+
74+ Keystone server support for user groups
75+
76+ This implements the server side of groups of users. This
77+ set of code provides all the crud functionality for groups as
78+ well as the corresponding support for role assignments.
79+
80+ blueprint user-groups
81+
82+ The following deficiencies existing with the current version and
83+ will be corrected ahead of the final Grizzly release:
84+
85+ 1) There is only placeholder support for LDAP (Bug #1092187)
86+ 2) Domain role grants are accepted but not yet honored (Bug #1093248)
87+ 3) Token invalidation does not occur with group changes (Bug #1093493)
88+
89+ This update also fills in missing v3 grant unit testing and v3 grant
90+ support within the kvs backend. In addition, there is a fix for
91+ Bug #1092200 (uncaught exception when listing grants)
92+
93+ DocImpact
94+
95+ Change-Id: Ibd1783b04b2d7804eff90312e5ef591dca4d0695
96+
97+ keystone/clean.py | 4 +
98+ keystone/common/models.py | 17 +
99+ .../migrate_repo/versions/013_add_group_tables.py | 93 +++++
100+ keystone/config.py | 11 +
101+ keystone/exception.py | 4 +
102+ keystone/identity/backends/kvs.py | 201 ++++++++++-
103+ keystone/identity/backends/ldap/core.py | 109 ++++++
104+ keystone/identity/backends/pam.py | 3 -
105+ keystone/identity/backends/sql.py | 362 +++++++++++++++++---
106+ keystone/identity/controllers.py | 103 ++++--
107+ keystone/identity/core.py | 113 +++++-
108+ keystone/identity/routers.py | 67 +++-
109+ keystone/service.py | 1 +
110+ keystone/token/controllers.py | 70 +++-
111+ tests/test_auth.py | 39 +++
112+ tests/test_backend.py | 306 +++++++++++++++++
113+ tests/test_backend_ldap.py | 47 +++
114+ tests/test_sql_upgrade.py | 18 +-
115+ tests/test_v3.py | 8 +
116+ tests/test_v3_identity.py | 199 ++++++++++-
117+ 20 files changed, 1669 insertions(+), 106 deletions(-)
118+
119+commit 3244451c1beb2236c99e1bace5925e4953b6771e
120+Author: Thierry Carrez <thierry@openstack.org>
121+Date: Mon Jan 7 14:37:53 2013 +0100
122+
123+ Add missing .po files to tarball
124+
125+ Fix MANIFEST.in to include .po files in keystone/locale.
126+ Fixes bug 1096063.
127+
128+ Change-Id: I4cf06a0777b5f22344ff18321bbf155f574b1e49
129+
130+ MANIFEST.in | 2 +-
131+ 1 file changed, 1 insertion(+), 1 deletion(-)
132+
133+commit 9460ff5c35809f4911cb5a1ee5f68d6351e797f4
134+Merge: 2162e4b 64672bd
135+Author: Jenkins <jenkins@review.openstack.org>
136+Date: Sat Jan 5 23:33:29 2013 +0000
137+
138+ Merge "Upgrade WebOb to 1.2.3"
139+
140+commit 2162e4b3b54f99095aa0f5f6fc3cbcad20436cc4
141+Merge: 2b08994 5a81be3
142+Author: Jenkins <jenkins@review.openstack.org>
143+Date: Sat Jan 5 23:25:14 2013 +0000
144+
145+ Merge "Removed unused imports"
146+
147+commit 2b08994e1f9d4ea7d7659faa014f541ed9a82e0e
148+Merge: 863acc7 0e5533e
149+Author: Jenkins <jenkins@review.openstack.org>
150+Date: Fri Jan 4 22:29:31 2013 +0000
151+
152+ Merge "il8n some strings"
153+
154+commit 863acc7b6d39de3596e2bf767397774053156f45
155+Merge: 76af49f 1f01d30
156+Author: Jenkins <jenkins@review.openstack.org>
157+Date: Thu Jan 3 19:30:53 2013 +0000
158+
159+ Merge "shorten pep8 output"
160+
161+commit 64672bdeb13097285af8dec16b6cacbef4495bab
162+Author: Doug Hellmann <doug.hellmann@dreamhost.com>
163+Date: Thu Jan 3 11:08:15 2013 -0500
164+
165+ Upgrade WebOb to 1.2.3
166+
167+ The version of WebOb being used in OpenStack was more than
168+ 1 year old. This change updates to the latest stable release.
169+
170+ Upgrading WebOb resolves a version conflict between OpenStack
171+ and Pecan, the web framework used by the Ceilometer team for
172+ version 2 of the ceilometer API.
173+
174+ Refer to http://docs.webob.org/en/latest/news.html
175+ for the list of changes between 1.0.8 and 1.2.3.
176+
177+ bug 1092227
178+
179+ Change-Id: If68866122e6c492b03887af5953ab7cad01787ba
180+ Signed-off-by: Doug Hellmann <doug.hellmann@dreamhost.com>
181+
182+ tools/pip-requires | 4 ++--
183+ 1 file changed, 2 insertions(+), 2 deletions(-)
184+
185+commit 0e5533eb6f828cffac1cdd98a524f69503332cec
186+Author: Chuck Short <chuck.short@canonical.com>
187+Date: Thu Jan 3 08:32:34 2013 -0600
188+
189+ il8n some strings
190+
191+ il8n some more missing strings.
192+
193+ Change-Id: I56d1d83093c8a5e895571e2d2db41c7600662754
194+ Signed-off-by: Chuck Short <chuck.short@canonical.com>
195+
196+ keystone/common/controller.py | 14 +++++++-------
197+ keystone/common/ldap/core.py | 16 ++++++++--------
198+ keystone/common/sql/migration.py | 2 +-
199+ keystone/common/utils.py | 4 ++--
200+ keystone/identity/backends/ldap/core.py | 2 +-
201+ 5 files changed, 19 insertions(+), 19 deletions(-)
202+
203+commit 76af49f11a5cd2ef7be93c5cbe3244fe48cc6b31
204+Author: OpenStack Jenkins <jenkins@openstack.org>
205+Date: Wed Jan 2 00:00:46 2013 +0000
206+
207+ Imported Translations from Transifex
208+
209+ Change-Id: I94d6360ce6f6ca8150a83c12af887452bc4a41f6
210+
211+ keystone/locale/hu/LC_MESSAGES/keystone.po | 313 ++++++++++++++++++++++++++++
212+ keystone/locale/keystone.pot | 18 +-
213+ 2 files changed, 324 insertions(+), 7 deletions(-)
214+
215+commit 5a81be30de7c756716aef06a361a88f553be9b76
216+Author: Chuck Short <chuck.short@canonical.com>
217+Date: Fri Dec 28 10:39:33 2012 -0600
218+
219+ Removed unused imports
220+
221+ Removed unused imports
222+
223+ Change-Id: I646d79849731b87ce6c1eeb80f42c77dd789ecff
224+ Signed-off-by: Chuck Short <chuck.short@canonical.com>
225+
226+ keystone/cli.py | 4 ----
227+ keystone/common/router.py | 1 -
228+ .../versions/001_add_initial_tables.py | 1 -
229+ .../sql/migrate_repo/versions/003_token_valid.py | 4 ----
230+ .../migrate_repo/versions/006_add_policy_table.py | 1 -
231+ .../migrate_repo/versions/007_add_domain_tables.py | 1 -
232+ .../versions/008_normalize_identity.py | 3 ---
233+ .../versions/009_normalize_identity_migration.py | 3 +--
234+ .../sql/migrate_repo/versions/010_endpoints_v3.py | 1 -
235+ .../versions/012_drop_legacy_endpoints.py | 1 -
236+ setup.py | 1 -
237+ tests/_ldap_livetest.py | 1 -
238+ 12 files changed, 1 insertion(+), 21 deletions(-)
239+
240+commit a0e06a8e96ccfeee1de0030da0a1a2ac9e6e5aad
241+Author: Chuck Short <chuck.short@canonical.com>
242+Date: Sat Dec 22 15:36:34 2012 -0600
243+
244+ Add pyflakes to tox.ini
245+
246+ Add the ability to use pyflakes.
247+
248+ Change-Id: I1c0a652258fd494bf6754b5b83c47166582a85d0
249+ Signed-off-by: Chuck Short <chuck.short@canonical.com>
250+
251+ tools/flakes.py | 22 ++++++++++++++++++++++
252+ tox.ini | 4 ++++
253+ 2 files changed, 26 insertions(+)
254+
255+commit daf3bdae226a76926a8a877e1ed4bd7046f9192d
256+Merge: 1b3b642 0f22574
257+Author: Jenkins <jenkins@review.openstack.org>
258+Date: Mon Dec 24 03:46:16 2012 +0000
259+
260+ Merge "Adding a means to connect back to a pydevd debugger."
261+
262+commit 1b3b6428225d16162bcb9d44ab628bccd9f219b4
263+Author: Chuck Short <chuck.short@canonical.com>
264+Date: Sat Dec 22 18:09:13 2012 -0600
265+
266+ Fix spelling typo
267+
268+ Fixes spelling typo should be role_id instead of roll_id.
269+
270+ Change-Id: I45a994f7cbe3528ef5a9a667a67237c2a896db9c
271+ Signed-off-by: Chuck Short <chuck.short@canonical.com>
272+
273+ keystone/identity/backends/ldap/core.py | 2 +-
274+ 1 file changed, 1 insertion(+), 1 deletion(-)
275+
276+commit 469ff6571e49f70662107a1db393b856214eea3c
277+Merge: 4fb7ef4 e577cd6
278+Author: Jenkins <jenkins@review.openstack.org>
279+Date: Sat Dec 22 20:39:42 2012 +0000
280+
281+ Merge "Remove swift auth."
282+
283+commit 4fb7ef4faf0b0ef3077c0175d158df3ab601e4bf
284+Merge: b5581fe 03eb280
285+Author: Jenkins <jenkins@review.openstack.org>
286+Date: Sat Dec 22 09:43:05 2012 +0000
287+
288+ Merge "Driver registry"
289+
290+commit 1f01d30983e3a67a146308ff8766f057bc5b7958
291+Author: Adam Young <ayoung@redhat.com>
292+Date: Thu Dec 20 21:43:41 2012 -0500
293+
294+ shorten pep8 output
295+
296+ This removes the PEP8 output that describes in detail how to fix each
297+ problem. It makes pep8 review so long that the earliest lines scroll
298+ out of the scrollback buffer before they can even be read.
299+
300+ With this change, each violation is on line long, which is
301+ much more readable.
302+
303+ Change-Id: I0d8cc64fd6027419754732e314c047b3775a121c
304+
305+ run_tests.sh | 2 +-
306+ 1 file changed, 1 insertion(+), 1 deletion(-)
307+
308+commit 03eb2801a3ad38a39e9cf127c05ab710bf38ee1d
309+Author: Dolph Mathews <dolph.mathews@rackspace.com>
310+Date: Wed Dec 19 10:04:21 2012 -0600
311+
312+ Driver registry
313+
314+ Uses automatic dependency injection to provide controllers with driver
315+ interfaces (identity_api, token_api, etc).
316+
317+ See tests/test_injection.py for a self-contained example.
318+
319+ Change-Id: I255087de534292fbf57a45b19f97488f831f607c
320+
321+ keystone/catalog/controllers.py | 11 ++-
322+ keystone/catalog/core.py | 2 +
323+ keystone/catalog/routers.py | 8 +-
324+ keystone/common/controller.py | 10 +--
325+ keystone/common/dependency.py | 67 +++++++++++++++++
326+ keystone/contrib/admin_crud/core.py | 17 ++---
327+ keystone/contrib/ec2/core.py | 17 ++---
328+ keystone/contrib/user_crud/core.py | 11 +--
329+ keystone/identity/controllers.py | 4 -
330+ keystone/identity/core.py | 8 +-
331+ keystone/identity/routers.py | 28 +++----
332+ keystone/policy/core.py | 2 +
333+ keystone/policy/routers.py | 4 +-
334+ keystone/routers.py | 13 ++--
335+ keystone/service.py | 32 ++++----
336+ keystone/test.py | 22 ++++--
337+ keystone/token/controllers.py | 2 +
338+ keystone/token/core.py | 4 +-
339+ keystone/token/routers.py | 6 +-
340+ tests/test_auth.py | 14 +---
341+ tests/test_injection.py | 141 +++++++++++++++++++++++++++++++++++
342+ 21 files changed, 297 insertions(+), 126 deletions(-)
343+
344+commit 0f225743e8644416df2f200d710912c40b7acd47
345+Author: John Bresnahan <jbresnah@redhat.com>
346+Date: Wed Dec 19 07:13:24 2012 -1000
347+
348+ Adding a means to connect back to a pydevd debugger.
349+
350+ That patch allows a developer to remotely run a pydev debugger and have the
351+ keystone-all process connect back to it. Two command line options are
352+ introduced:
353+ --pydev-debug-host <host>
354+ --pydev-debug-port <port>
355+ both of the above options are required to enable this behavior.
356+
357+ This patch only enables this behavior when the service is started with
358+ keystone-all. In the future parts of this patch can be used to enable
359+ this behavior when running in Apache.
360+
361+ Change-Id: I92f99fa34112336a96e42e8261b7313f23ee994e
362+
363+ bin/keystone-all | 7 +++++++
364+ keystone/common/utils.py | 19 +++++++++++++++++++
365+ keystone/config.py | 3 +++
366+ 3 files changed, 29 insertions(+)
367+
368+commit b5581fea95f96dc7e43abe2b28c99678b5219238
369+Merge: ac2d92c a591b30
370+Author: Jenkins <jenkins@review.openstack.org>
371+Date: Fri Dec 21 03:29:40 2012 +0000
372+
373+ Merge "add in pip requires for requests"
374+
375+commit a591b3010c37f19924775f52c8076778888f1ade
376+Author: Adam Young <ayoung@redhat.com>
377+Date: Thu Dec 20 16:40:20 2012 -0500
378+
379+ add in pip requires for requests
380+
381+ Change-Id: I0f5ac9a4008dc471cefea7a6ffe44d4c51950538
382+
383+ tools/pip-requires | 2 +-
384+ tools/test-requires | 2 ++
385+ 2 files changed, 3 insertions(+), 1 deletion(-)
386+
387+commit ac2d92ca2eea1070f765be320acb62fd5bef6dd3
388+Merge: 1a0d30b 2f85134
389+Author: Jenkins <jenkins@review.openstack.org>
390+Date: Tue Dec 18 18:01:40 2012 +0000
391+
392+ Merge "Split endpoint records in SQL by interface"
393+
394+commit 2f851340ee8969193b9dcc1913401aa9b33c5d97
395+Author: Dolph Mathews <dolph.mathews@rackspace.com>
396+Date: Fri Nov 30 12:52:26 2012 -0600
397+
398+ Split endpoint records in SQL by interface
399+
400+ This migrates the SQL backend such that v2 endpoints containing up to 3
401+ URL's (public, internal and admin) stored in 'extra' are split into
402+ unique endpoints.
403+
404+ Because legacy "endpoints" (each having publicUrl, internalUrl and
405+ adminUrl) are no longer conceptually identical to v3's "endpoints" (each
406+ having an interface and a url), new ID's are assigned to each entity and
407+ each API continues to operate using with independent sets of endpoint
408+ ID's.
409+
410+ Endpoints created on the v3 API are not exposed on the v2 API.
411+
412+ Change-Id: I2ba59d55907313ae65e908585fc49be0c4ce899a
413+
414+ keystone/catalog/backends/sql.py | 54 +++---
415+ keystone/catalog/controllers.py | 65 ++++++-
416+ .../sql/migrate_repo/versions/010_endpoints_v3.py | 54 ++++++
417+ .../versions/011_populate_endpoint_type.py | 96 ++++++++++
418+ .../versions/012_drop_legacy_endpoints.py | 51 ++++++
419+ tests/test_backend.py | 3 +
420+ tests/test_backend_sql.py | 78 ++++----
421+ tests/test_sql_upgrade.py | 191 +++++++++++++++++---
422+ tests/test_v3.py | 1 +
423+ 9 files changed, 487 insertions(+), 106 deletions(-)
424+
425+commit 1a0d30bf0173f8e03abeac4bda2e807bd4f29412
426+Merge: 4f4b4a7 5b3a74d
427+Author: Jenkins <jenkins@review.openstack.org>
428+Date: Tue Dec 18 16:56:10 2012 +0000
429+
430+ Merge "Support non-default role_id_attribute"
431+
432+commit 4f4b4a7b5b0d846e308f2ce693d3c6e69f944d1e
433+Merge: 7db702c f74aab2
434+Author: Jenkins <jenkins@review.openstack.org>
435+Date: Tue Dec 18 16:55:48 2012 +0000
436+
437+ Merge "Expand default time delta (bug 1089988)"
438+
439+commit 7db702cab1f2cad8160aeadc8c1ae27853b8a34c
440+Merge: ede7e20 fb963a5
441+Author: Jenkins <jenkins@review.openstack.org>
442+Date: Tue Dec 18 14:43:26 2012 +0000
443+
444+ Merge "module refactoring"
445+
446+commit ede7e209bded5494a2453485e619b7b81f23cf3a
447+Merge: 96d2ff7 23ba963
448+Author: Jenkins <jenkins@review.openstack.org>
449+Date: Mon Dec 17 23:54:12 2012 +0000
450+
451+ Merge "Fix typo s/interalurl/internalurl/"
452+
453+commit 96d2ff71ad01d53232cdc128df9d3b6109a04f67
454+Merge: 7093c55 8e2a183
455+Author: Jenkins <jenkins@review.openstack.org>
456+Date: Mon Dec 17 21:45:00 2012 +0000
457+
458+ Merge "Test drivers return HTTP 501 Not Implemented"
459+
460+commit 7093c55d2e4722fc8ffdcef594cc5705b586a2d9
461+Merge: 44e3c3e d17dfe6
462+Author: Jenkins <jenkins@review.openstack.org>
463+Date: Mon Dec 17 21:44:38 2012 +0000
464+
465+ Merge "Import pysqlite2 if sqlite3 is not available."
466+
467+commit 23ba963af45c0243d817ae38a84f9e3c830415eb
468+Author: Mark J. Washenberger <mark.washenberger@markwash.net>
469+Date: Mon Dec 17 13:41:39 2012 -0800
470+
471+ Fix typo s/interalurl/internalurl/
472+
473+ Change-Id: I9e9209731e5d13b21a7aff6127d932d69c457135
474+
475+ keystone/common/models.py | 2 +-
476+ 1 file changed, 1 insertion(+), 1 deletion(-)
477+
478+commit fb963a560939e6be8c98d74e5555de7283173e32
479+Author: Adam Young <ayoung@redhat.com>
480+Date: Wed Dec 12 13:17:54 2012 -0500
481+
482+ module refactoring
483+
484+ Distributes the functionality of service.py into the modules.
485+ Moves ComposableRouters into the modules.
486+ The routers and controllers now have short names.
487+ The controllers get their APIs via the base class.
488+
489+ Change-Id: I87404b80ea9800d6792f97a7a3a64fe839065c1c
490+
491+ keystone/catalog/__init__.py | 1 +
492+ keystone/catalog/controllers.py | 20 +-
493+ keystone/catalog/routers.py | 25 ++
494+ keystone/common/router.py | 57 +++++
495+ keystone/contrib/admin_crud/core.py | 18 +-
496+ keystone/contrib/user_crud/core.py | 23 +-
497+ keystone/controllers.py | 144 +++++++++++
498+ keystone/identity/controllers.py | 24 +-
499+ keystone/identity/routers.py | 73 +++++-
500+ keystone/policy/__init__.py | 1 +
501+ keystone/policy/routers.py | 22 ++
502+ keystone/routers.py | 68 +++++
503+ keystone/service.py | 472 ++---------------------------------
504+ keystone/token/__init__.py | 1 +
505+ keystone/token/routers.py | 61 +++++
506+ 15 files changed, 503 insertions(+), 507 deletions(-)
507+
508+commit 44e3c3ece3f6e8a596dbec37476d8fb5c85d6f6c
509+Merge: ebfbd6c e093e81
510+Author: OpenStack Jenkins <jenkins@openstack.org>
511+Date: Fri Dec 14 20:13:31 2012 +0000
512+
513+ Merge "Imported Translations from Transifex"
514+
515+commit ebfbd6c0844f9ab3e9a864112672164cf8b3696f
516+Merge: d939d16 be3dcf9
517+Author: Jenkins <jenkins@review.openstack.org>
518+Date: Fri Dec 14 20:13:10 2012 +0000
519+
520+ Merge "Test for content-type appropriate 404 (bug 1089987)"
521+
522+commit d939d16e747b4a2c5db1f1fdda93a01b79fe6e83
523+Merge: f5d26ea 18a49ae
524+Author: Jenkins <jenkins@review.openstack.org>
525+Date: Fri Dec 14 15:20:07 2012 +0000
526+
527+ Merge "syncing run_tests to match tox"
528+
529+commit f5d26ea9c67e2bb812f0e7a36512538b9f3e18ff
530+Merge: 5b7160c 6ceb066
531+Author: Jenkins <jenkins@review.openstack.org>
532+Date: Fri Dec 14 15:04:46 2012 +0000
533+
534+ Merge "fixing bug 1046862"
535+
536+commit be3dcf9873fb84bbb5c2cd3ed8f36444f353757e
537+Author: Dolph Mathews <dolph.mathews@rackspace.com>
538+Date: Thu Dec 13 10:01:21 2012 -0600
539+
540+ Test for content-type appropriate 404 (bug 1089987)
541+
542+ Change-Id: Idfba75f90e38de315ec50e660932beb8243f76f8
543+
544+ keystone/common/wsgi.py | 2 +-
545+ tests/test_content_types.py | 12 ++++++++++++
546+ 2 files changed, 13 insertions(+), 1 deletion(-)
547+
548+commit e093e81c750408478d74fafac2cb0cc7eb221d5f
549+Author: OpenStack Jenkins <jenkins@openstack.org>
550+Date: Fri Dec 14 00:01:05 2012 +0000
551+
552+ Imported Translations from Transifex
553+
554+ Change-Id: Ib2cb912443034b4d9855441ca83d103e2a9bdbe8
555+
556+ keystone/locale/keystone.pot | 276 +++++++++++++++++++++++++++++++++++++++++-
557+ 1 file changed, 275 insertions(+), 1 deletion(-)
558+
559+commit 5b7160cd536f0a86cf33bc294679bd19a2e90549
560+Merge: 4e2be8a e4d61ac
561+Author: Jenkins <jenkins@review.openstack.org>
562+Date: Thu Dec 13 22:11:33 2012 +0000
563+
564+ Merge "Add tests for contrib.s3.core."
565+
566+commit 6ceb06689f5f1da26584192ae9f46a5248277565
567+Author: Steve Martinelli <stevemar@ca.ibm.com>
568+Date: Thu Dec 13 11:35:01 2012 -0500
569+
570+ fixing bug 1046862
571+
572+ adding message to readme.rst to include openSSL dependency
573+
574+ fixing bug 1046862
575+
576+ Change-Id: Iff1fbc95e804f9e4ddc74ea38c553426c4eabb33
577+
578+ README.rst | 7 +++++++
579+ 1 file changed, 7 insertions(+)
580+
581+commit f74aab2463ccc9549c07175ed82015f23ad2694c
582+Author: Dolph Mathews <dolph.mathews@rackspace.com>
583+Date: Thu Dec 13 09:42:32 2012 -0600
584+
585+ Expand default time delta (bug 1089988)
586+
587+ Change-Id: I3d08092bf5248f75b238591586443a4daea02a20
588+
589+ keystone/test.py | 9 ++++++---
590+ 1 file changed, 6 insertions(+), 3 deletions(-)
591+
592+commit e4d61ac6a7893743ff47c0a69529c5f21f249127
593+Author: Chmouel Boudjnah <chmouel@chmouel.com>
594+Date: Wed Dec 12 19:04:23 2012 +0100
595+
596+ Add tests for contrib.s3.core.
597+
598+ Change-Id: I0a5ea82dcbcf29f6581d8c69e8961138fa019145
599+
600+ tests/test_contrib_s3_core.py | 54 +++++++++++++++++++++++++++++++++++++++++
601+ 1 file changed, 54 insertions(+)
602+
603+commit 8e2a183992311fe005abbfaa40d68dd7ce1fffd3
604+Author: Dolph Mathews <dolph.mathews@rackspace.com>
605+Date: Mon Dec 10 10:10:22 2012 -0600
606+
607+ Test drivers return HTTP 501 Not Implemented
608+
609+ Change-Id: I4cd21022593e6b4c3965edd00ecea01a00584516
610+
611+ keystone/policy/core.py | 2 +-
612+ keystone/token/backends/kvs.py | 14 +++++-----
613+ keystone/token/backends/memcache.py | 8 +++---
614+ keystone/token/backends/sql.py | 8 +++---
615+ keystone/token/controllers.py | 5 ++--
616+ keystone/token/core.py | 44 ++++++++++++++++-------------
617+ tests/test_drivers.py | 52 +++++++++++++++++++++++++++++++++++
618+ 7 files changed, 96 insertions(+), 37 deletions(-)
619+
620+commit 5b3a74d56a376afed64dd2515c4aa59995187433
621+Author: Dolph Mathews <dolph.mathews@rackspace.com>
622+Date: Wed Dec 12 15:01:04 2012 -0600
623+
624+ Support non-default role_id_attribute
625+
626+ As is, a default value of 'cn' is hardcoded as the attribute name (which
627+ also happens to be the default value in keystone.config) used for role
628+ grants, revokes, etc.
629+
630+ Change-Id: Ic36e6d726e2dc48714703c2dd7a433f3d34b78b1
631+
632+ keystone/identity/backends/ldap/core.py | 3 ++-
633+ 1 file changed, 2 insertions(+), 1 deletion(-)
634+
635+commit e577cd60871e1810b45236d3642d60e460dc4858
636+Author: Chmouel Boudjnah <chmouel@chmouel.com>
637+Date: Sat Dec 8 13:38:45 2012 +0100
638+
639+ Remove swift auth.
640+
641+ - This has been moved since last release to swift main repository.
642+
643+ Change-Id: I11fc4001fbc4a1d78823d41450cdfcc97677c420
644+
645+ doc/source/configuringservices.rst | 147 +----------------
646+ keystone/middleware/swift_auth.py | 295 -----------------------------------
647+ tests/test_swift_auth_middleware.py | 249 -----------------------------
648+ 3 files changed, 2 insertions(+), 689 deletions(-)
649+
650+commit 4e2be8a8880f03b1c6d1dc663d7259dbb45ddf67
651+Author: Dolph Mathews <dolph.mathews@rackspace.com>
652+Date: Tue Dec 11 14:40:27 2012 -0600
653+
654+ Move token controller into keystone.token
655+
656+ Change-Id: Ie8277529185f645854e0aebaafa173c06a7c5164
657+
658+ keystone/common/controller.py | 12 +-
659+ keystone/contrib/ec2/core.py | 5 +-
660+ keystone/service.py | 556 ++---------------------------------------
661+ keystone/token/__init__.py | 1 +
662+ keystone/token/controllers.py | 545 ++++++++++++++++++++++++++++++++++++++++
663+ tests/test_auth.py | 358 ++++++++++++++++++++++++++
664+ tests/test_service.py | 355 --------------------------
665+ 7 files changed, 927 insertions(+), 905 deletions(-)
666+
667+commit 6397580a52be5288b4cb5e0a86a8c340fe4fd0ae
668+Merge: bf4b9f4 0ea864b
669+Author: Jenkins <jenkins@review.openstack.org>
670+Date: Tue Dec 11 14:03:52 2012 +0000
671+
672+ Merge "Adding downgrade steps for migration scripts."
673+
674+commit d17dfe65550d393739dc50a1eedfe65903a81d28
675+Author: Yuriy Taraday <yorik.sar@gmail.com>
676+Date: Fri Dec 7 22:32:52 2012 +0400
677+
678+ Import pysqlite2 if sqlite3 is not available.
679+
680+ Otherwise test_import_legacy fails on import.
681+
682+ Change-Id: I902493f5b726f5bc9e23e776598b8938c85e622c
683+
684+ tests/test_import_legacy.py | 8 +++++---
685+ 1 file changed, 5 insertions(+), 3 deletions(-)
686+
687+commit bf4b9f49878e85000b197ea9c2627cc67fda5cdb
688+Merge: d159c61 aaf61a4
689+Author: Jenkins <jenkins@review.openstack.org>
690+Date: Mon Dec 10 22:14:15 2012 +0000
691+
692+ Merge "Remove mentions of essex in docs (bug 1085247)"
693+
694+commit d159c616fd52436760242d3254c8bdb54810bcb4
695+Merge: a800fae 847d591
696+Author: Jenkins <jenkins@review.openstack.org>
697+Date: Mon Dec 10 21:44:54 2012 +0000
698+
699+ Merge "Port to argparse based cfg"
700+
701+commit aaf61a4fc9d07a73d2a31abb097a2d862598c4e5
702+Author: Eduardo Patrocinio <epatro@gmail.com>
703+Date: Tue Dec 4 15:11:16 2012 -0500
704+
705+ Remove mentions of essex in docs (bug 1085247)
706+
707+ Change-Id: I663e9317c2b5eb5fe7190ea6c656fcebff7078fd
708+
709+ doc/source/configuration.rst | 20 ++++++++++----------
710+ 1 file changed, 10 insertions(+), 10 deletions(-)
711+
712+commit a800fae22c627e89a09ffc35b95dd072416da14a
713+Author: Brian Waldon <brian.waldon@rackspace.com>
714+Date: Thu Dec 6 12:31:51 2012 -0800
715+
716+ Ensure serviceCatalog is list when empty, not dict
717+
718+ Fixes bug 1087405.
719+
720+ Change-Id: I152c7f418a66ccfe541e26efe75b59bffa6c3849
721+
722+ keystone/service.py | 2 +-
723+ tests/test_content_types.py | 19 +++++++++++++++++--
724+ 2 files changed, 18 insertions(+), 3 deletions(-)
725+
726+commit 0ea864b26e6e2e9be44785af61fd90a9b13b5265
727+Author: Justin Shepherd <jshepher@rackspace.com>
728+Date: Mon Nov 26 17:37:02 2012 +0000
729+
730+ Adding downgrade steps for migration scripts.
731+
732+ Also updated test_sql_upgrade to check the actions from 007_add_domain_tables.
733+
734+ Fixes: bug #1081167
735+
736+ Change-Id: I194c7de9ae8a3bb8f2f9f37d3a91f4fac2fe2913
737+
738+ .../versions/001_add_initial_tables.py | 9 +++++++-
739+ .../migrate_repo/versions/003_sqlite_downgrade.sql | 1 -
740+ .../migrate_repo/versions/006_add_policy_table.py | 6 ++++-
741+ .../migrate_repo/versions/007_add_domain_tables.py | 5 ++++
742+ tests/test_sql_upgrade.py | 24 ++++++++++++++++++++
743+ 5 files changed, 42 insertions(+), 3 deletions(-)
744+
745+commit 7978bb271bf0e978a095aa088e4bb2bdb1d684f8
746+Merge: 3583946 84a0b2d
747+Author: Jenkins <jenkins@review.openstack.org>
748+Date: Wed Dec 5 21:21:39 2012 +0000
749+
750+ Merge "Bug 1075090 -- Fixing log messages in python source code to support internationalization."
751+
752+commit 3583946d933b989b14c25daa9d6c462142eb400f
753+Merge: 9b529c8 c858c1b
754+Author: Jenkins <jenkins@review.openstack.org>
755+Date: Wed Dec 5 21:08:07 2012 +0000
756+
757+ Merge "Only 'import *' from 'core' modules"
758+
759+commit 9b529c8c00fc344d5a5e33170e95ba5f1bee0fed
760+Merge: 8c15e3e 77dee93
761+Author: Jenkins <jenkins@review.openstack.org>
762+Date: Wed Dec 5 21:07:51 2012 +0000
763+
764+ Merge "use keystone test and change config during setUp"
765+
766+commit 847d5912d383072e3c38d6d19fce15981ca3110a
767+Author: Mark McLoughlin <markmc@redhat.com>
768+Date: Mon Nov 26 14:39:49 2012 +0000
769+
770+ Port to argparse based cfg
771+
772+ Sync the following changes from oslo-incubator:
773+
774+ 3557d84 Fix ListOpt to trim whitespace
775+ 01ab910 Fix set_default() with boolean CLI options
776+ af18eaa Improve cfg's argparse sub-parsers support
777+ f21e1d9 Fix regression with cfg CLI arguments
778+ ceb4aa7 Fix broken --help with CommonConfigOpts
779+ 5e9503b Hide the GroupAttr conf and group attributes
780+ b6d24bb updating sphinx documentation
781+ 403509e Don't reference argparse._StoreAction
782+ e17deb8 Fix minor coding style issue
783+ 0c29e1d Remove ConfigCliParser class
784+ 5b9cb41 Add support for positional arguments
785+ dbc72a6 Use stock argparse behaviour for optional args
786+ 768a147 Use stock argparse --usage behaviour
787+ ac180b9 Use stock argparse --version behaviour
788+ 0787e38 Remove add_option() method
789+ 5afead0 Completely remove cfg's disable_interspersed_args()
790+ 5f564b2 argparse support for cfg
791+ d7b6397 Add a missing comma in a docstring.
792+ aca1805 cfg: fix required if option has a dash
793+
794+ The main API change affecting keystone is that CONF() no longer returns
795+ unparsed arguments. The keystone-manage command is updated to use
796+ argparse sub-parsers to achieve the same effect.
797+
798+ Change-Id: Ie8972ce851f1247d8710e9e0611bb3e2f843cb45
799+
800+ keystone/cli.py | 133 +++++------
801+ keystone/openstack/common/cfg.py | 451 ++++++++++++++++++++++++--------------
802+ 2 files changed, 345 insertions(+), 239 deletions(-)
803+
804+commit c858c1b304cae6310f08a220cf54c763f684fc42
805+Author: Dolph Mathews <dolph.mathews@rackspace.com>
806+Date: Wed Dec 5 09:58:54 2012 -0600
807+
808+ Only 'import *' from 'core' modules
809+
810+ - Renamed identity.controllers.* and identity.routers.* since they
811+ now occopy unique namespaces (thanks ayoung!)
812+ - Moved catalog and policy controllers into their own respective modules
813+
814+ Change-Id: Ib9e277355e0eac15d4d218785c816b718b493b5b
815+
816+ HACKING.rst | 2 +-
817+ keystone/catalog/__init__.py | 1 +
818+ keystone/catalog/controllers.py | 154 +++++++++++++++++++++++++++++++++++
819+ keystone/catalog/core.py | 136 -------------------------------
820+ keystone/contrib/admin_crud/core.py | 10 +--
821+ keystone/contrib/user_crud/core.py | 11 ++-
822+ keystone/identity/__init__.py | 4 +-
823+ keystone/identity/controllers.py | 28 +++----
824+ keystone/identity/routers.py | 25 ++----
825+ keystone/policy/__init__.py | 1 +
826+ keystone/policy/controllers.py | 48 +++++++++++
827+ keystone/policy/core.py | 32 --------
828+ keystone/service.py | 20 ++---
829+ 13 files changed, 246 insertions(+), 226 deletions(-)
830+
831+commit 77dee93763e4941b07f628c1c67d925503a5df51
832+Author: Ionuț Arțăriși <iartarisi@suse.cz>
833+Date: Mon Dec 3 11:59:20 2012 +0100
834+
835+ use keystone test and change config during setUp
836+
837+ Also fixes this traceback which I keep getting on devstack:
838+
839+ ERROR: test_create_certs (tests.test_cert_setup.CertSetupTestCase)
840+ ----------------------------------------------------------------------
841+ Traceback (most recent call last):
842+ File "/opt/stack/keystone/tests/test_cert_setup.py", line 52, in tearDown
843+ shutil.rmtree(rootdir(SSLDIR))
844+ File "/usr/lib/python2.7/shutil.py", line 237, in rmtree
845+ onerror(os.listdir, path, sys.exc_info())
846+ File "/usr/lib/python2.7/shutil.py", line 235, in rmtree
847+ names = os.listdir(path)
848+ OSError: [Errno 2] No such file or directory: '/opt/stack/keystone/tests/ssl/'
849+
850+ Fixes bug 1086812
851+
852+ Change-Id: Iba10822aaf1284549d610bb1172df03ffc48f363
853+
854+ tests/test_cert_setup.py | 16 +++++++++-------
855+ 1 file changed, 9 insertions(+), 7 deletions(-)
856+
857+commit 84a0b2df5932fabb0cdaaaddeb86d1f55a7ac06e
858+Author: Nachiappan VR N <nachiappan.veerappan-nachiappan@hp.com>
859+Date: Wed Nov 14 10:01:59 2012 -0800
860+
861+ Bug 1075090 -- Fixing log messages in python source code to support internationalization.
862+
863+ Change-Id: I6b50abaa82effad8feaaac8d85086ca8b5d42590
864+
865+ keystone/catalog/backends/templated.py | 2 +-
866+ keystone/catalog/core.py | 16 +++++-----
867+ keystone/clean.py | 13 ++++----
868+ keystone/common/bufferedhttp.py | 4 +--
869+ keystone/common/cms.py | 4 +--
870+ keystone/common/ldap/core.py | 17 +++++-----
871+ keystone/common/ldap/fakeldap.py | 54 +++++++++++++++++---------------
872+ keystone/common/sql/core.py | 2 +-
873+ keystone/common/sql/legacy.py | 2 +-
874+ keystone/common/sql/nova.py | 14 ++++-----
875+ keystone/common/utils.py | 10 +++---
876+ keystone/common/wsgi.py | 6 ++--
877+ keystone/config.py | 4 +--
878+ keystone/policy/backends/rules.py | 2 +-
879+ keystone/test.py | 2 +-
880+ 15 files changed, 80 insertions(+), 72 deletions(-)
881+
882+commit 8c15e3eba68d4af655eacee3d1ec46e98911d119
883+Author: Alvaro Lopez Garcia <aloga@ifca.unican.es>
884+Date: Mon Dec 3 10:12:06 2012 +0100
885+
886+ Added documentation for the external auth support
887+
888+ This covers given authentication using REMOTE_USER and also the way to
889+ implement custom auth with WSGI middleware.
890+
891+ DocImpact
892+ blueprint: pluggable-identity-authentication-handlers
893+ Change-Id: Idbac8c38d1f0be1febbbc8056c929bada6bbb07e
894+
895+ doc/source/external-auth.rst | 117 ++++++++++++++++++++++++++++++++++++++++++
896+ doc/source/index.rst | 1 +
897+ 2 files changed, 118 insertions(+)
898+
899+commit 75277cf1ae496145369e929702005ef2304e6942
900+Merge: 5b73757 af8761d
901+Author: Jenkins <jenkins@review.openstack.org>
902+Date: Mon Dec 3 09:57:36 2012 +0000
903+
904+ Merge "check the redirected path on the request, not the response"
905+
906+commit af8761d9e0add62a83604b77ab015f5a8b3120a9
907+Author: Ionuț Arțăriși <iartarisi@suse.cz>
908+Date: Fri Nov 30 14:04:04 2012 +0100
909+
910+ check the redirected path on the request, not the response
911+
912+ The request object's path changes when it gets redirected. This
913+ behaviour is in tune with the latest WebOb code as well as the
914+ old. The response environ defaults to None in WebOb >= 1.2b1
915+ http://docs.webob.org/en/latest/news.html#b1
916+
917+ Change-Id: I557563ce5407a8ef1b5dae680e456e589285be25
918+
919+ tests/test_s3_token_middleware.py | 8 ++++----
920+ 1 file changed, 4 insertions(+), 4 deletions(-)
921+
922+commit 5b73757de94a30b7cc8566e2bf429c1aecd5c320
923+Author: Wu Wenxiang <wu.wenxiang@99cloud.net>
924+Date: Thu Nov 29 23:58:04 2012 +0800
925+
926+ Validate password type (bug 1081861)
927+
928+ Raise keystone.exception.ValidationError when password type was not string
929+
930+ Change-Id: Ib7538806777db0fe3a3cf9f22bf06a1d505c232f
931+
932+ keystone/common/utils.py | 12 ++++++++----
933+ 1 file changed, 8 insertions(+), 4 deletions(-)
934+
935+commit f57098df8e50fae95c2c532407ec5bc6a10205e1
936+Author: Adam Young <ayoung@redhat.com>
937+Date: Wed Nov 28 17:27:43 2012 -0500
938+
939+ split identities module into logical parts
940+ remove unneeded imports from core
941+
942+ Change-Id: I02fc2439cc115878d8081e052faf9ff96d20f6ec
943+
944+ keystone/identity/__init__.py | 2 +
945+ keystone/identity/controllers.py | 607 +++++++++++++++++++++++++++++++++++++
946+ keystone/identity/core.py | 614 --------------------------------------
947+ keystone/identity/routers.py | 72 +++++
948+ 4 files changed, 681 insertions(+), 614 deletions(-)
949+
950+commit 38c7e46a640a94da4da89a39a5a1ea9c081f1eb5
951+Author: Dolph Mathews <dolph.mathews@rackspace.com>
952+Date: Wed Nov 28 10:28:07 2012 -0500
953+
954+ Ensure token expiration is maintained (bug 1079216)
955+
956+ Change-Id: I95853ec36e9c4cd937cfac7e08b648e830f9efd0
957+
958+ keystone/service.py | 1 +
959+ tests/test_service.py | 57 +++++++++++++++++++++++++++++++++++++++++++++++++
960+ 2 files changed, 58 insertions(+)
961+
962+commit ede63fbfe504cffb4b29f7394b1bf4872d093588
963+Merge: d970e5f 1012bd4
964+Author: Jenkins <jenkins@review.openstack.org>
965+Date: Tue Nov 27 19:49:22 2012 +0000
966+
967+ Merge "normalize identity"
968+
969+commit 1012bd42df5906bca67a82663f23b5c8a4eafe68
970+Author: Adam Young <ayoung@redhat.com>
971+Date: Tue Nov 6 17:16:56 2012 -0500
972+
973+ normalize identity
974+
975+ modify tables by adding columns, and modify entities
976+ by adding attributes for password, description and enabled
977+
978+ update tests to deal with change from 'False' and 'True' to the
979+ python values False and True
980+
981+ Added a Text type from SQL Alchemy
982+
983+ Bug 1070351
984+ Bug 1023544
985+
986+ Change-Id: I066c788b5d08a8f42a9b5412ea9e29e4fe9ba205
987+
988+ keystone/common/sql/core.py | 1 +
989+ .../versions/008_normalize_identity.py | 61 ++++++++
990+ .../migrate_repo/versions/008_sqlite_downgrade.sql | 5 +
991+ .../versions/009_normalize_identity_migration.py | 146 ++++++++++++++++++++
992+ keystone/identity/backends/sql.py | 8 +-
993+ tests/default_fixtures.py | 8 ++
994+ tests/test_backend.py | 18 +--
995+ tests/test_backend_sql.py | 2 +
996+ tests/test_sql_upgrade.py | 53 ++++++-
997+ 9 files changed, 290 insertions(+), 12 deletions(-)
998+
999+commit d970e5f815558706e5be642d814d08c93b0dd42a
1000+Merge: 3779c67 d4c4cf0
1001+Author: Jenkins <jenkins@review.openstack.org>
1002+Date: Tue Nov 27 04:22:51 2012 +0000
1003+
1004+ Merge "Fixes typo in keystone setup doc"
1005+
1006+commit d4c4cf035120c22c222b16c963abb1b82c33a707
1007+Author: Tom Fifield <fifieldt@unimelb.edu.au>
1008+Date: Tue Nov 27 12:38:07 2012 +1000
1009+
1010+ Fixes typo in keystone setup doc
1011+
1012+ fixes bug 1083391
1013+
1014+ A one character change to fix a typo in setup doc, reported
1015+ by a user :s
1016+
1017+ Change-Id: I4fefec089c9ded4b773f4b3641e30162a4faa2f8
1018+
1019+ doc/source/setup.rst | 2 +-
1020+ 1 file changed, 1 insertion(+), 1 deletion(-)
1021+
1022+commit 3779c675c54fbc2be9d341e2a2a77b520f0f3a59
1023+Author: OpenStack Jenkins <jenkins@openstack.org>
1024+Date: Tue Nov 27 00:01:43 2012 +0000
1025+
1026+ Imported Translations from Transifex
1027+
1028+ Change-Id: I2cb4f8bd3891b474413eef11aae62188b358d359
1029+
1030+ keystone/locale/keystone.pot | 10 +---------
1031+ 1 file changed, 1 insertion(+), 9 deletions(-)
1032+
1033+commit 904af119d2b84a93e416b7b297eda3b321840669
1034+Author: Mark McLoughlin <markmc@redhat.com>
1035+Date: Mon Nov 26 16:16:54 2012 +0000
1036+
1037+ Stop using cfg's internal implementation details
1038+
1039+ The fact that a cfg opt register using register_opt() is available via
1040+ the command line is actually a bug (see bug #1082279).
1041+
1042+ Also, using the _cli_values attribute is clearly poking into private
1043+ implementation details.
1044+
1045+ Fix both issues by registering the opt using register_cli_opt() and
1046+ accessing its value the normal way.
1047+
1048+ Change-Id: If170dcd96daae5b4c3d7cdebed914df417c2209b
1049+
1050+ bin/keystone-all | 2 +-
1051+ keystone/config.py | 4 +++-
1052+ 2 files changed, 4 insertions(+), 2 deletions(-)
1053+
1054+commit 18a49ae5767cc9cf0f81d3bb9616aba4f076178a
1055+Author: Joe Heck <heckj@mac.com>
1056+Date: Wed Nov 21 22:02:19 2012 +0000
1057+
1058+ syncing run_tests to match tox
1059+
1060+ Change-Id: Ide81b1ea9230ceb2ad463d4f253eb7021fc683da
1061+
1062+ run_tests.sh | 2 +-
1063+ 1 file changed, 1 insertion(+), 1 deletion(-)
1064+
1065 commit 07c1aafdf20db6d6d7c0d3e15074bc02e2f1d2aa
1066 Merge: d8aa7fd 01fccdb
1067 Author: Jenkins <jenkins@review.openstack.org>
1068
1069=== modified file 'HACKING.rst'
1070--- HACKING.rst 2012-11-02 13:48:49 +0000
1071+++ HACKING.rst 2013-01-25 16:27:23 +0000
1072@@ -44,7 +44,7 @@
1073 Imports
1074 -------
1075
1076-- Do not import objects, only modules
1077+- Import modules, not module attributes
1078 - Do not import more than one module per line
1079 - Do not make relative imports
1080 - Order your imports by the full module path
1081
1082=== modified file 'MANIFEST.in'
1083--- MANIFEST.in 2012-08-16 13:59:29 +0000
1084+++ MANIFEST.in 2013-01-25 16:27:23 +0000
1085@@ -18,5 +18,5 @@
1086 graft tests
1087 graft tools
1088 graft examples
1089-recursive-include keystone *.json *.xml *.cfg *.pem README *.pot *.sql
1090+recursive-include keystone *.json *.xml *.cfg *.pem README *.po *.pot *.sql
1091 global-exclude *.pyc *.sdx *.log *.db *.swp
1092
1093=== modified file 'README.rst'
1094--- README.rst 2012-05-24 14:04:20 +0000
1095+++ README.rst 2013-01-25 16:27:23 +0000
1096@@ -212,3 +212,10 @@
1097
1098 In the backend this would look up the policy for 'action:nova:add_network' and
1099 then do what is effectively a 'Simple Match' style match against the creds.
1100+
1101+
1102+----------------------------------
1103+Dependencies
1104+----------------------------------
1105+
1106+Ensure an OpenSSL version of 1.0+ is installed.
1107\ No newline at end of file
1108
1109=== modified file 'bin/keystone-all'
1110--- bin/keystone-all 2012-11-02 13:48:49 +0000
1111+++ bin/keystone-all 2013-01-25 16:27:23 +0000
1112@@ -90,7 +90,14 @@
1113 CONF.print_help()
1114 sys.exit(1)
1115
1116- monkeypatch_thread = not CONF._cli_values['standard_threads']
1117+ monkeypatch_thread = not CONF.standard_threads
1118+ pydev_debug_url = utils.setup_remote_pydev_debug()
1119+ if pydev_debug_url:
1120+ # in order to work around errors caused by monkey patching we have to
1121+ # set the thread to False. An explanation is here:
1122+ # http://lists.openstack.org/pipermail/openstack-dev/2012-August/
1123+ # 000794.html
1124+ monkeypatch_thread = False
1125 eventlet.patcher.monkey_patch(all=False, socket=True, time=True,
1126 thread=monkeypatch_thread)
1127
1128
1129=== modified file 'debian/changelog'
1130--- debian/changelog 2012-11-26 19:24:17 +0000
1131+++ debian/changelog 2013-01-25 16:27:23 +0000
1132@@ -1,3 +1,36 @@
1133+keystone (2013.1~g2-0ubuntu1~cloud0) precise-grizzly; urgency=low
1134+
1135+ * New upstream release for the Ubuntu Cloud Archive.
1136+
1137+ -- Chuck Short <zulcss@ubuntu.com> Wed, 23 Jan 2013 12:27:47 -0600
1138+
1139+keystone (2013.1~g2-0ubuntu1) raring; urgency=low
1140+
1141+ [ James Page ]
1142+ * Re-enable gating of package build based on successful unit testing:
1143+ - d/tests/test_overrides.conf: Fixup test configuration to use
1144+ correct certificate locations.
1145+ - d/p/fix-ubuntu-tests.patch: Skip tests for older versions of
1146+ keystoneclient based on checkouts of upstream git repo.
1147+ - d/rules: Re-enable package build failure on test failure.
1148+ * d/control: Bump dependencies on python-keystoneclient to >= 1:0.2.
1149+ * d/control: Update Vcs-Bzr location to point to correct branch.
1150+ * d/control,d/po/*: Setup package templates for translation.
1151+ * d/man/*: Corrected spellings in man pages.
1152+ * d/keystone.upstart: Tweak 'stop on' to be triggered on all
1153+ appropriate runlevel transitions, use start-stop-daemon to startup
1154+ keystone daemon.
1155+
1156+ [ Adam Gandelman ]
1157+ * debian/keystone.manpages: Install sphinx-generated manpages instead
1158+ of our own outdated and unneeded versions. (LP: #1082050)
1159+
1160+ [ Chuck Short ]
1161+ * New upstream release.
1162+ * Remove incomplete/broken dbconfig-common scripts.
1163+
1164+ -- Chuck Short <zulcss@ubuntu.com> Fri, 11 Jan 2013 08:47:26 -0600
1165+
1166 keystone (2013.1~g1-0ubuntu1~cloud0) precise-grizzly; urgency=low
1167
1168 * New upstream release for the Ubuntu Cloud Archive.
1169
1170=== modified file 'debian/control'
1171--- debian/control 2012-11-02 13:48:49 +0000
1172+++ debian/control 2013-01-25 16:27:23 +0000
1173@@ -6,11 +6,12 @@
1174 Uploaders: Soren Hansen <soren@ubuntu.com>
1175 Build-Depends: debhelper (>= 7.0.50),
1176 pep8,
1177+ po-debconf,
1178 pylint,
1179 python-all (>= 2.6),
1180 python-all-dev (>= 2.6.6-3~) | python-support,
1181 python-eventlet,
1182- python-keystoneclient ( >= 1:0.1.3 ),
1183+ python-keystoneclient ( >= 1:0.2 ),
1184 python-ldap,
1185 python-lxml,
1186 python-memcache,
1187@@ -33,7 +34,7 @@
1188 Standards-Version: 3.9.3
1189 XS-Python-Version: >= 2.6
1190 Homepage: http://launchpad.net/keystone
1191-Vcs-Bzr: https://code.launchpad.net/~ubuntu-server-dev/keystone/essex
1192+Vcs-Bzr: https://code.launchpad.net/~openstack-ubuntu-testing/keystone/grizzly
1193
1194 Package: python-keystone
1195 Architecture: all
1196@@ -52,7 +53,7 @@
1197 python-sqlalchemy,
1198 python-migrate,
1199 python-prettytable,
1200- python-keystoneclient ( >= 1:0.1.3 ),
1201+ python-keystoneclient ( >= 1:0.2 ),
1202 python-webob,
1203 python-iso8601
1204 Suggests: python-memcache
1205@@ -76,8 +77,7 @@
1206 Depends: ${python:Depends}, ${misc:Depends},
1207 python-keystone (= ${source:Version}),
1208 adduser,
1209- ssl-cert (>= 1.0.12),
1210- dbconfig-common
1211+ ssl-cert (>= 1.0.12)
1212 Description: OpenStack identity service - Daemons
1213 Keystone is a proposed independent authentication service for OpenStack.
1214 .
1215
1216=== removed file 'debian/keystone.config'
1217--- debian/keystone.config 2012-06-22 12:27:50 +0000
1218+++ debian/keystone.config 1970-01-01 00:00:00 +0000
1219@@ -1,19 +0,0 @@
1220-#!/bin/sh
1221-set -e
1222-
1223-. /usr/share/debconf/confmodule
1224-
1225-
1226-db_input low keystone/configure_db || true
1227-db_go
1228-db_get keystone/configure_db
1229-if [ "$RET" = "true" ]; then
1230- if [ -f /usr/share/dbconfig-common/dpkg/config ];
1231- then
1232- dbc_dbtypes="sqlite3, mysql, pgsql"
1233- db_authmethod_user="password"
1234- dbc_basepath="/var/lib/keystone"
1235- . /usr/share/dbconfig-common/dpkg/config
1236- dbc_go keystone $@
1237- fi
1238-fi
1239
1240=== modified file 'debian/keystone.manpages'
1241--- debian/keystone.manpages 2011-12-16 15:38:05 +0000
1242+++ debian/keystone.manpages 2013-01-25 16:27:23 +0000
1243@@ -1,1 +1,1 @@
1244-debian/man/*
1245+doc/build/man/*
1246
1247=== modified file 'debian/keystone.postinst'
1248--- debian/keystone.postinst 2012-03-02 09:55:24 +0000
1249+++ debian/keystone.postinst 2013-01-25 16:27:23 +0000
1250@@ -2,8 +2,6 @@
1251
1252 set -e
1253
1254-. /usr/share/debconf/confmodule
1255-. /usr/share/dbconfig-common/dpkg/postinst
1256
1257 # summary of how this script can be called:
1258 # * <new-preinst> `install'
1259@@ -19,30 +17,10 @@
1260 #su -s /bin/sh -c 'exec keystone database sync' keystone
1261 ;;
1262 configure)
1263- db_get keystone/configure_db
1264- if [ "$RET" = "true" ]; then
1265- dbc_go keystone $@
1266-
1267- case "$dbc_dbtype" in
1268- sqlite3)
1269- SQL_CONNECTION="sqlite:///$dbc_basepath/$dbc_dbname.db"
1270- ;;
1271- mysql)
1272- [ -n "$dbc_dbport" ] && dbport=:$dbc_dbport
1273- SQL_CONNECTION="mysql://$dbc_dbuser:$dbc_dbpass@${dbc_dbserver:-localhost}$dbport/$dbc_dbname"
1274- ;;
1275- pgsql)
1276- [ -n "$dbc_dbport" ] && dbport=:$dbc_dbport
1277- SQL_CONNECTION="pgsql://$dbc_dbuser:$dbc_dbpass@${dbc_dbserver:-localhost}$dbport/$dbc_dbname"
1278- ;;
1279- *)
1280- SQL_CONNECTION="sqlite:////var/lib/keystone/keystone.db"
1281- ;;
1282- esac
1283- [ -z "$2" -o "$dbc_install" = "true" ] \
1284- && sed -e "s,_DBC_URL_,$SQL_CONNECTION," -i /etc/keystone/keystone.conf
1285+ if ! grep -q sql_connection /etc/keystone/keystone.conf
1286+ then
1287+ su -s /bin/sh -c 'exec keystone-manage db_sync' keystone
1288 fi
1289- su -s /bin/sh -c 'exec keystone-manage db_sync' keystone
1290 ;;
1291 abort-upgrade)
1292 echo "aport upgrade called"
1293
1294=== modified file 'debian/keystone.postrm'
1295--- debian/keystone.postrm 2012-06-22 12:27:50 +0000
1296+++ debian/keystone.postrm 2013-01-25 16:27:23 +0000
1297@@ -2,20 +2,6 @@
1298
1299 set -e
1300
1301-if [ -f /usr/share/debconf/confmodule ]
1302-then
1303- . /usr/share/debconf/confmodule
1304-fi
1305-
1306-if [ -f /etc/dbconfig-common/keystone.conf ]
1307-then
1308- if [ -f /usr/share/dbconfig-common/dpkg/postrm ]
1309- then
1310- . /usr/share/dbconfig-common/dpkg/postrm
1311- dbc_go keystone $@
1312- fi
1313-fi
1314-
1315 case "$1" in
1316 purge)
1317 rm -rf /var/log/keystone
1318
1319=== removed file 'debian/keystone.prerm'
1320--- debian/keystone.prerm 2012-06-22 12:27:50 +0000
1321+++ debian/keystone.prerm 1970-01-01 00:00:00 +0000
1322@@ -1,17 +0,0 @@
1323-#!/bin/sh
1324-
1325-set -e
1326-
1327-. /usr/share/debconf/confmodule
1328-. /usr/share/dbconfig-common/dpkg/prerm
1329-
1330-
1331-db_get keystone/configure_db
1332-if [ "$RET" = "true" ]; then
1333- # Only cleanup with dbconfig if it was used during
1334- # installation (LP: #948719)
1335- dbc_go keystone $@
1336-fi
1337-
1338-#DEBHELPER#
1339-
1340
1341=== modified file 'debian/keystone.templates'
1342--- debian/keystone.templates 2012-06-22 12:27:50 +0000
1343+++ debian/keystone.templates 2013-01-25 16:27:23 +0000
1344@@ -1,7 +1,7 @@
1345 Template: keystone/configure_db
1346 Type: boolean
1347 Default: false
1348-Description: Set up a database for keystone?
1349+_Description: Set up a database for keystone?
1350 No database has been set up for keystone to use. Before continuing,
1351 you should make sure you have:
1352 .
1353
1354=== modified file 'debian/keystone.upstart'
1355--- debian/keystone.upstart 2012-06-22 12:27:50 +0000
1356+++ debian/keystone.upstart 2013-01-25 16:27:23 +0000
1357@@ -2,8 +2,10 @@
1358 author "Soren Hansen <soren@linux2go.dk>"
1359
1360 start on (local-filesystems and net-device-up IFACE!=lo)
1361-stop on runlevel [016]
1362+stop on runlevel [!2345]
1363
1364 respawn
1365
1366-exec su -s /bin/sh -c "exec keystone-all" keystone
1367+exec start-stop-daemon --start --chuid keystone \
1368+ --chdir /var/lib/keystone --name keystone \
1369+ --exec /usr/bin/keystone-all
1370
1371=== removed directory 'debian/man'
1372=== removed file 'debian/man/keystone-admin.8'
1373--- debian/man/keystone-admin.8 2012-06-22 12:27:50 +0000
1374+++ debian/man/keystone-admin.8 1970-01-01 00:00:00 +0000
1375@@ -1,63 +0,0 @@
1376-.TH keystone 8
1377-.SH NAME
1378-keystone-admin \- provides HTTP for administrators.
1379-.SH SYNOPSIS
1380-.I [OPTION]...
1381-.SH DESCRIPTION
1382-.BR keystone is a Python implementation of the Openstack
1383-identity service.
1384-.TP
1385-.B --version
1386-show program's version number and exit
1387-.TP
1388-.B \-h, --help
1389-show help messag and exit
1390-.TP
1391-.B \-v, --verbose
1392-Print more verbose output
1393-.TP
1394-.B \-d, --debug
1395-Prrint debugging output to console.
1396-.TP
1397-.B \-c PATH, --config-file=PATH
1398-Path to the config file to use. When not specified (the default),
1399-we generally look at the first arguement specified to be a config file,
1400-and if that is also missing, we search standard directories for a config
1401-file.
1402-.TP
1403-.B \-p BIND_PORT, --port=BIND_PORT, --bind-port=BIND_PORT
1404-Specifies port to listen on.
1405-.TP
1406-.B --host=BIND_HOST, --bind-host=BIND_HOST
1407-Specifies host address to listen on (default is all or 0.0.0.0)
1408-.TP
1409-.B \-t, --trace-calls
1410-Turns on call tracing for troubleshooting
1411-.TP
1412-.B \-a PORT, --admin-port=PORT
1413-Specifies port for Admin API to listen on (default is
1414-35357)
1415-.TP
1416-.B --log-config=PATH
1417-If this opion is specified, the logging configuration
1418-file specified is used and overrides any other logging
1419-options specified. Please see the Python logging
1420-modules documentation for details on logging
1421-confgiuration files.
1422-.TP
1423-.B --log-date-format=FORMAT
1424-Format string for %(asctime)s in log records.
1425-Default: %Y-%m-%d %H:%M:%S
1426-.TP
1427-.B --log-file=PATH
1428-(Optional) Name of log file to output to. If not set,
1429-logging will go to stdout.
1430-.TP
1431-.B --log-didr=LOG_DIR
1432-(Optional) The directory to keep log files in (will
1433-be prepended to --logfile)
1434-
1435-.SH FILES
1436-.IR /etc/keystone/keystone.conf
1437-.SH AUTHOR
1438-This manual page was written by Chuck Short <zulcss@ubuntu.com>.
1439
1440=== removed file 'debian/man/keystone-auth.8'
1441--- debian/man/keystone-auth.8 2012-06-22 12:27:50 +0000
1442+++ debian/man/keystone-auth.8 1970-01-01 00:00:00 +0000
1443@@ -1,63 +0,0 @@
1444-.TH keystone 8
1445-.SH NAME
1446-keystone-auth \- provides HTTP for users.
1447-.SH SYNOPSIS
1448-.I [OPTION]...
1449-.SH DESCRIPTION
1450-.BR keystone is a Python implementation of the Openstack
1451-identity service.
1452-.TP
1453-.B --version
1454-show program's version number and exit
1455-.TP
1456-.B \-h, --help
1457-show help messag and exit
1458-.TP
1459-.B \-v, --verbose
1460-Print more verbose output
1461-.TP
1462-.B \-d, --debug
1463-Prrint debugging output to console.
1464-.TP
1465-.B \-c PATH, --config-file=PATH
1466-Path to the config file to use. When not specified (the default),
1467-we generally look at the first arguement specified to be a config file,
1468-and if that is also missing, we search standard directories for a config
1469-file.
1470-.TP
1471-.B \-p BIND_PORT, --port=BIND_PORT, --bind-port=BIND_PORT
1472-Specifies port to listen on.
1473-.TP
1474-.B --host=BIND_HOST, --bind-host=BIND_HOST
1475-Specifies host address to listen on (default is all or 0.0.0.0)
1476-.TP
1477-.B \-t, --trace-calls
1478-Turns on call tracing for troubleshooting
1479-.TP
1480-.B \-a PORT, --admin-port=PORT
1481-Specifies port for Admin API to listen on (default is
1482-35357)
1483-.TP
1484-.B --log-config=PATH
1485-If this opion is specified, the logging configuration
1486-file specified is used and overrides any other logging
1487-options specified. Please see the Python logging
1488-modules documentation for details on logging
1489-confgiuration files.
1490-.TP
1491-.B --log-date-format=FORMAT
1492-Format string for %(asctime)s in log records.
1493-Default: %Y-%m-%d %H:%M:%S
1494-.TP
1495-.B --log-file=PATH
1496-(Optional) Name of log file to output to. If not set,
1497-logging will go to stdout.
1498-.TP
1499-.B --log-didr=LOG_DIR
1500-(Optional) The directory to keep log files in (will
1501-be prepended to --logfile)
1502-
1503-.SH FILES
1504-.IR /etc/keystone/keystone.conf
1505-.SH AUTHOR
1506-This manual page was written by Chuck Short <zulcss@ubuntu.com>.
1507
1508=== removed file 'debian/man/keystone-control.8'
1509--- debian/man/keystone-control.8 2012-06-22 12:27:50 +0000
1510+++ debian/man/keystone-control.8 1970-01-01 00:00:00 +0000
1511@@ -1,63 +0,0 @@
1512-.TH keystone 8
1513-.SH NAME
1514-keystone \- Starts/Stops keystone server.
1515-.SH SYNOPSIS
1516-.I [OPTION]...
1517-.SH DESCRIPTION
1518-.BR keystone is a Python implementation of the Openstack
1519-identity service.
1520-.TP
1521-.B --version
1522-show program's version number and exit
1523-.TP
1524-.B \-h, --help
1525-show help messag and exit
1526-.TP
1527-.B \-v, --verbose
1528-Print more verbose output
1529-.TP
1530-.B \-d, --debug
1531-Prrint debugging output to console.
1532-.TP
1533-.B \-c PATH, --config-file=PATH
1534-Path to the config file to use. When not specified (the default),
1535-we generally look at the first arguement specified to be a config file,
1536-and if that is also missing, we search standard directories for a config
1537-file.
1538-.TP
1539-.B \-p BIND_PORT, --port=BIND_PORT, --bind-port=BIND_PORT
1540-Specifies port to listen on.
1541-.TP
1542-.B --host=BIND_HOST, --bind-host=BIND_HOST
1543-Specifies host address to listen on (default is all or 0.0.0.0)
1544-.TP
1545-.B \-t, --trace-calls
1546-Turns on call tracing for troubleshooting
1547-.TP
1548-.B \-a PORT, --admin-port=PORT
1549-Specifies port for Admin API to listen on (default is
1550-35357)
1551-.TP
1552-.B --log-config=PATH
1553-If this opion is specified, the logging configuration
1554-file specified is used and overrides any other logging
1555-options specified. Please see the Python logging
1556-modules documentation for details on logging
1557-confgiuration files.
1558-.TP
1559-.B --log-date-format=FORMAT
1560-Format string for %(asctime)s in log records.
1561-Default: %Y-%m-%d %H:%M:%S
1562-.TP
1563-.B --log-file=PATH
1564-(Optional) Name of log file to output to. If not set,
1565-logging will go to stdout.
1566-.TP
1567-.B --log-didr=LOG_DIR
1568-(Optional) The directory to keep log files in (will
1569-be prepended to --logfile)
1570-
1571-.SH FILES
1572-.IR /etc/keystone/keystone.conf
1573-.SH AUTHOR
1574-This manual page was written by Chuck Short <zulcss@ubuntu.com>.
1575
1576=== removed file 'debian/man/keystone-import.8'
1577--- debian/man/keystone-import.8 2012-06-22 12:27:50 +0000
1578+++ debian/man/keystone-import.8 1970-01-01 00:00:00 +0000
1579@@ -1,12 +0,0 @@
1580-.TH keystone 8
1581-.SH NAME
1582-keystone-import \- import users, tenants, and EC2 credentials from nova.
1583-.SH SYNOPSIS
1584-.I [OPTION]...
1585-.SH DESCRIPTION
1586-.BR keystone is a Python implementation of the Openstack
1587-identity service.
1588-.SH FILES
1589-.IR /etc/keystone/keystone.conf
1590-.SH AUTHOR
1591-This manual page was written by Chuck Short <zulcss@ubuntu.com>.
1592
1593=== removed file 'debian/man/keystone.8'
1594--- debian/man/keystone.8 2012-06-22 12:27:50 +0000
1595+++ debian/man/keystone.8 1970-01-01 00:00:00 +0000
1596@@ -1,64 +0,0 @@
1597-.TH keystone 8
1598-.SH NAME
1599-keystone \- provides HTTP for administrators and users.
1600-.SH SYNOPSIS
1601-.I [OPTION]...
1602-.SH DESCRIPTION
1603-.B keystone is a Python implementation of the Openstack
1604-.B identity service. This version has a lack of SSL support.
1605-.B It should not be run on a trusted network.
1606-.TP
1607-.B --version
1608-show program's version number and exit
1609-.TP
1610-.B \-h, --help
1611-show help messag and exit
1612-.TP
1613-.B \-v, --verbose
1614-Print more verbose output
1615-.TP
1616-.B \-d, --debug
1617-Prrint debugging output to console.
1618-.TP
1619-.B \-c PATH, --config-file=PATH
1620-Path to the config file to use. When not specified (the default),
1621-we generally look at the first arguement specified to be a config file,
1622-and if that is also missing, we search standard directories for a config
1623-file.
1624-.TP
1625-.B \-p BIND_PORT, --port=BIND_PORT, --bind-port=BIND_PORT
1626-Specifies port to listen on.
1627-.TP
1628-.B --host=BIND_HOST, --bind-host=BIND_HOST
1629-Specifies host address to listen on (default is all or 0.0.0.0)
1630-.TP
1631-.B \-t, --trace-calls
1632-Turns on call tracing for troubleshooting
1633-.TP
1634-.B \-a PORT, --admin-port=PORT
1635-Specifies port for Admin API to listen on (default is
1636-35357)
1637-.TP
1638-.B --log-config=PATH
1639-If this opion is specified, the logging configuration
1640-file specified is used and overrides any other logging
1641-options specified. Please see the Python logging
1642-modules documentation for details on logging
1643-confgiuration files.
1644-.TP
1645-.B --log-date-format=FORMAT
1646-Format string for %(asctime)s in log records.
1647-Default: %Y-%m-%d %H:%M:%S
1648-.TP
1649-.B --log-file=PATH
1650-(Optional) Name of log file to output to. If not set,
1651-logging will go to stdout.
1652-.TP
1653-.B --log-didr=LOG_DIR
1654-(Optional) The directory to keep log files in (will
1655-be prepended to --logfile)
1656-
1657-.SH FILES
1658-.IR /etc/keystone/keystone.conf
1659-.SH AUTHOR
1660-This manual page was written by Chuck Short <zulcss@ubuntu.com>.
1661
1662=== modified file 'debian/patches/fix-ubuntu-tests.patch'
1663--- debian/patches/fix-ubuntu-tests.patch 2012-11-23 09:01:53 +0000
1664+++ debian/patches/fix-ubuntu-tests.patch 2013-01-25 16:27:23 +0000
1665@@ -1,6 +1,16 @@
1666-diff -Naurp keystone-2013.1.orig/tests/test_keystoneclient.py keystone-2013.1/tests/test_keystoneclient.py
1667---- keystone-2013.1.orig/tests/test_keystoneclient.py 2012-11-22 03:19:01.000000000 -0600
1668-+++ keystone-2013.1/tests/test_keystoneclient.py 2012-11-22 10:24:20.729138227 -0600
1669+Description: Fix test execution during package build
1670+ The keystoneclient testsuite includes a number of tests
1671+ for older version of keystone which are retrieved from
1672+ the upstream source repo during testing.
1673+ .
1674+ This is not possible during an offline package build so
1675+ the checkout and tests are disabled/skipped.
1676+Author: Chuck Short <zulcss@ubuntu.com>
1677+Author: James Page <james.page@ubuntu.com>
1678+Forwarded: not-needed
1679+
1680+--- a/tests/test_keystoneclient.py
1681++++ b/tests/test_keystoneclient.py
1682 @@ -35,10 +35,6 @@ class CompatTestCase(test.TestCase):
1683 def setUp(self):
1684 super(CompatTestCase, self).setUp()
1685@@ -12,3 +22,28 @@
1686 self.load_backends()
1687 self.load_fixtures(default_fixtures)
1688
1689+@@ -1003,6 +999,16 @@ class KcMasterTestCase(CompatTestCase, K
1690+ client.tenants.list()
1691+
1692+
1693++def skipped(func):
1694++ from nose.plugins.skip import SkipTest
1695++
1696++ def _():
1697++ raise SkipTest("Test %s is skipped" % func.__name__)
1698++ _.__name__ = func.__name__
1699++ return _
1700++
1701++
1702++@skipped
1703+ class KcEssex3TestCase(CompatTestCase, KeystoneClientTests):
1704+ def get_checkout(self):
1705+ return KEYSTONECLIENT_REPO, 'essex-3'
1706+@@ -1101,6 +1107,7 @@ class KcEssex3TestCase(CompatTestCase, K
1707+ raise nose.exc.SkipTest('N/A')
1708+
1709+
1710++@skipped
1711+ class Kc11TestCase(CompatTestCase, KeystoneClientTests):
1712+ def get_checkout(self):
1713+ return KEYSTONECLIENT_REPO, '0.1.1'
1714
1715=== added directory 'debian/po'
1716=== added file 'debian/po/POTFILES.in'
1717--- debian/po/POTFILES.in 1970-01-01 00:00:00 +0000
1718+++ debian/po/POTFILES.in 2013-01-25 16:27:23 +0000
1719@@ -0,0 +1,1 @@
1720+[type: gettext/rfc822deb] keystone.templates
1721
1722=== added file 'debian/po/templates.pot'
1723--- debian/po/templates.pot 1970-01-01 00:00:00 +0000
1724+++ debian/po/templates.pot 2013-01-25 16:27:23 +0000
1725@@ -0,0 +1,58 @@
1726+# SOME DESCRIPTIVE TITLE.
1727+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
1728+# This file is distributed under the same license as the PACKAGE package.
1729+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
1730+#
1731+#, fuzzy
1732+msgid ""
1733+msgstr ""
1734+"Project-Id-Version: keystone\n"
1735+"Report-Msgid-Bugs-To: keystone@packages.debian.org\n"
1736+"POT-Creation-Date: 2012-11-25 22:21+0000\n"
1737+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1738+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1739+"Language-Team: LANGUAGE <LL@li.org>\n"
1740+"Language: \n"
1741+"MIME-Version: 1.0\n"
1742+"Content-Type: text/plain; charset=CHARSET\n"
1743+"Content-Transfer-Encoding: 8bit\n"
1744+
1745+#. Type: boolean
1746+#. Description
1747+#: ../keystone.templates:1001
1748+msgid "Set up a database for keystone?"
1749+msgstr ""
1750+
1751+#. Type: boolean
1752+#. Description
1753+#: ../keystone.templates:1001
1754+msgid ""
1755+"No database has been set up for keystone to use. Before continuing, you "
1756+"should make sure you have:"
1757+msgstr ""
1758+
1759+#. Type: boolean
1760+#. Description
1761+#: ../keystone.templates:1001
1762+msgid ""
1763+" - the server host name (that server must allow TCP connections\n"
1764+" from this machine);\n"
1765+" - a username and password to access the database.\n"
1766+" - A database type that you want to use."
1767+msgstr ""
1768+
1769+#. Type: boolean
1770+#. Description
1771+#: ../keystone.templates:1001
1772+msgid ""
1773+"If some of these requirements are missing, reject this option and run with "
1774+"regular sqlite support."
1775+msgstr ""
1776+
1777+#. Type: boolean
1778+#. Description
1779+#: ../keystone.templates:1001
1780+msgid ""
1781+"Database configuration can be reconfigured later by running 'dpkg-"
1782+"reconfigure -plow keystone'."
1783+msgstr ""
1784
1785=== modified file 'debian/rules'
1786--- debian/rules 2012-11-23 09:01:53 +0000
1787+++ debian/rules 2013-01-25 16:27:23 +0000
1788@@ -26,7 +26,7 @@
1789 cp tests/test_overrides.conf tests/test_overrides.conf.orig
1790 cp $(CURDIR)/debian/tests/test_overrides.conf $(CURDIR)/tests/test_overrides.conf
1791 sed -i 's|%CUR_DIR%|$(CURDIR)|g' $(CURDIR)/tests/test_overrides.conf
1792- PYTHONPATH=$(CURDIR) bash run_tests.sh -N || true
1793+ PYTHONPATH=$(CURDIR) bash run_tests.sh -N
1794 mv $(CURDIR)/tests/test_overrides.conf.orig $(CURDIR)/tests/test_overrides.conf
1795 rm -rf $(CURDIR)/debian/tests/testing.db $(CURDIR)/debian/tests/keystone-signing
1796 endif
1797
1798=== modified file 'debian/tests/test_overrides.conf'
1799--- debian/tests/test_overrides.conf 2012-11-02 13:48:49 +0000
1800+++ debian/tests/test_overrides.conf 2013-01-25 16:27:23 +0000
1801@@ -13,6 +13,6 @@
1802 idle_timeout = 200
1803
1804 [signing]
1805-certfile = signing/signing_cert.pem
1806-keyfile = signing/private_key.pem
1807-ca_certs = signing/cacert.pem
1808+certfile = ../examples/pki/certs/signing_cert.pem
1809+keyfile = ../examples/pki/private/signing_key.pem
1810+ca_certs = ../examples/pki/certs/cacert.pem
1811
1812=== modified file 'doc/source/configuration.rst'
1813--- doc/source/configuration.rst 2012-11-23 09:01:53 +0000
1814+++ doc/source/configuration.rst 2013-01-25 16:27:23 +0000
1815@@ -388,10 +388,10 @@
1816 * ``etc/logging.conf.sample``
1817 * ``etc/default_catalog.templates``
1818
1819-.. _`prepare your Essex deployment`:
1820+.. _`prepare your deployment`:
1821
1822-Preparing your Essex deployment
1823-===============================
1824+Preparing your deployment
1825+=========================
1826
1827 Step 1: Configure keystone.conf
1828 -------------------------------
1829@@ -450,9 +450,9 @@
1830 .. NOTE::
1831
1832 Before you can import your legacy data, you must first
1833- `prepare your Essex deployment`_.
1834+ `prepare your deployment`_.
1835
1836-Step 1: Ensure your Essex deployment can access your legacy database
1837+Step 1: Ensure your deployment can access your legacy database
1838 --------------------------------------------------------------------
1839
1840 Your legacy ``keystone.conf`` contains a SQL configuration section called
1841@@ -461,7 +461,7 @@
1842
1843 sql_connection = sqlite:///keystone.db
1844
1845-This connection string needs to be accessible from your Essex deployment (e.g.
1846+This connection string needs to be accessible from your deployment (e.g.
1847 you may need to copy your SQLite ``*.db`` file to a new server, adjust the
1848 relative path as appropriate, or open a firewall for MySQL, etc).
1849
1850@@ -474,7 +474,7 @@
1851 $ keystone-manage import_legacy <sql_connection>
1852
1853 You should now be able to run the same command you used to test your new
1854-database above, but now you'll see your legacy Keystone data in Essex::
1855+database above, but now you'll see your legacy Keystone data::
1856
1857 $ keystone --token ADMIN --endpoint http://127.0.0.1:35357/v2.0/ tenant-list
1858 +----------------------------------+----------------+---------+
1859@@ -491,7 +491,7 @@
1860 ===============================================================
1861
1862 While legacy Keystone deployments stored the service catalog in the database,
1863-the service catalog in Essex is stored in a flat ``template_file``. An example
1864+the service catalog is stored in a flat ``template_file``. An example
1865 service catalog template file may be found in
1866 ``etc/default_catalog.templates``. You can change the path to your service
1867 catalog template in ``keystone.conf`` by changing the value of
1868@@ -510,13 +510,13 @@
1869 ========================
1870
1871 Migration of users, projects (aka tenants), roles and EC2 credentials
1872-is supported for the Essex release of Nova. To migrate your auth
1873+is supported for the Essex and later releases of Nova. To migrate your auth
1874 data from Nova, use the following steps:
1875
1876 .. NOTE::
1877
1878 Before you can migrate from nova auth, you must first
1879- `prepare your Essex deployment`_.
1880+ `prepare your deployment`_.
1881
1882 Step 1: Export your data from Nova
1883 ----------------------------------
1884
1885=== modified file 'doc/source/configuringservices.rst'
1886--- doc/source/configuringservices.rst 2012-09-07 13:04:01 +0000
1887+++ doc/source/configuringservices.rst 2013-01-25 16:27:23 +0000
1888@@ -176,151 +176,8 @@
1889 ---------------------------------
1890
1891 Similar to Nova, swift can be configured to use Keystone for authentication
1892-rather than its built in 'tempauth'.
1893-
1894-1. Add a service endpoint for Swift to Keystone
1895-
1896-2. Configure the paste file for swift-proxy (`/etc/swift/swift-proxy.conf`)
1897-
1898-3. Reconfigure Swift's proxy server to use Keystone instead of TempAuth.
1899- Here's an example `/etc/swift/proxy-server.conf`::
1900-
1901- [DEFAULT]
1902- bind_port = 8888
1903- user = <user>
1904-
1905- [pipeline:main]
1906- pipeline = catch_errors healthcheck cache authtoken keystone proxy-server
1907-
1908- [app:proxy-server]
1909- use = egg:swift#proxy
1910- account_autocreate = true
1911-
1912- [filter:keystone]
1913- paste.filter_factory = keystone.middleware.swift_auth:filter_factory
1914- operator_roles = admin, swiftoperator
1915-
1916- [filter:authtoken]
1917- paste.filter_factory = keystone.middleware.auth_token:filter_factory
1918- # Delaying the auth decision is required to support token-less
1919- # usage for anonymous referrers ('.r:*') or for tempurl/formpost
1920- # middleware.
1921- delay_auth_decision = 1
1922- auth_port = 35357
1923- auth_host = 127.0.0.1
1924- auth_token = ADMIN
1925- admin_token = ADMIN
1926-
1927- [filter:cache]
1928- use = egg:swift#memcache
1929- set log_name = cache
1930-
1931- [filter:catch_errors]
1932- use = egg:swift#catch_errors
1933-
1934- [filter:healthcheck]
1935- use = egg:swift#healthcheck
1936-
1937-.. Note::
1938- Your user needs to have the role swiftoperator or admin by default
1939- to be able to operate on an swift account or as specified by the
1940- variable `operator_roles`.
1941-
1942-4. Restart swift
1943-
1944-5. Verify that keystone is providing authentication to Swift
1945-
1946- $ swift -V 2 -A http://localhost:5000/v2.0 -U admin:admin -K ADMIN stat
1947-
1948-.. NOTE::
1949- Instead of connecting to Swift here, as you would with other services, we
1950- are connecting directly to Keystone.
1951-
1952-Configuring Swift with S3 emulation to use Keystone
1953----------------------------------------------------
1954-
1955-Keystone supports validating S3 tokens using the same tokens as the
1956-generated EC2 tokens. When you have generated a pair of EC2 access
1957-token and secret you can access your swift cluster directly with the
1958-S3 API.
1959-
1960-1. Ensure you have defined the S3 service in your `keystone.conf`. First, define the filter as follows::
1961-
1962- [filter:s3_extension]
1963- paste.filter_factory = keystone.contrib.s3:S3Extension.factory
1964-
1965-Then, ensure that the filter is being called by the admin_api pipeline, as follows::
1966-
1967- [pipeline:admin_api]
1968- pipeline = token_auth [....] ec2_extension s3_extension [...]
1969-
1970-2. Configure the paste file for swift-proxy
1971- (`/etc/swift/swift-proxy.conf` to use S3token and Swift3
1972- middleware.
1973-
1974- Here's an example that by default communicates with keystone via https ::
1975-
1976- [DEFAULT]
1977- bind_port = 8080
1978- user = <user>
1979-
1980- [pipeline:main]
1981- pipeline = catch_errors healthcheck cache swift3 s3token authtoken keystone proxy-server
1982-
1983- [app:proxy-server]
1984- use = egg:swift#proxy
1985- account_autocreate = true
1986-
1987- [filter:catch_errors]
1988- use = egg:swift#catch_errors
1989-
1990- [filter:healthcheck]
1991- use = egg:swift#healthcheck
1992-
1993- [filter:cache]
1994- use = egg:swift#memcache
1995-
1996- [filter:swift3]
1997- use = egg:swift#swift3
1998-
1999- [filter:keystone]
2000- paste.filter_factory = keystone.middleware.swift_auth:filter_factory
2001- operator_roles = admin, swiftoperator
2002-
2003- [filter:s3token]
2004- paste.filter_factory = keystone.middleware.s3_token:filter_factory
2005- # uncomment the following line if you don't want to use SSL
2006- # auth_protocol = http
2007- auth_port = 35357
2008- auth_host = 127.0.0.1
2009-
2010- [filter:authtoken]
2011- paste.filter_factory = keystone.middleware.auth_token:filter_factory
2012- # uncomment the following line if you don't want to use SSL
2013- # auth_protocol = http
2014- auth_port = 35357
2015- auth_host = 127.0.0.1
2016- auth_token = ADMIN
2017- admin_token = ADMIN
2018-
2019-3. You can then access directly your Swift via the S3 API, here's an
2020- example with the `boto` library::
2021-
2022- import boto
2023- import boto.s3.connection
2024-
2025- connection = boto.connect_s3(
2026- aws_access_key_id='<ec2 access key for user>',
2027- aws_secret_access_key='<ec2 secret access key for user>',
2028- port=8080,
2029- host='localhost',
2030- is_secure=False,
2031- calling_format=boto.s3.connection.OrdinaryCallingFormat())
2032-
2033-
2034-.. Note::
2035- With the S3 middleware you are connecting to the `Swift` proxy and
2036- not to `keystone`.
2037+rather than its built in 'tempauth'. Refer to the `overview_auth` documentation
2038+in Swift.
2039
2040 Auth-Token Middleware with Username and Password
2041 ------------------------------------------------
2042
2043=== added file 'doc/source/external-auth.rst'
2044--- doc/source/external-auth.rst 1970-01-01 00:00:00 +0000
2045+++ doc/source/external-auth.rst 2013-01-25 16:27:23 +0000
2046@@ -0,0 +1,117 @@
2047+===========================================
2048+Using external authentication with Keystone
2049+===========================================
2050+
2051+When Keystone is executed in :doc:`HTTPD <apache-httpd>` it is possible to
2052+use external authentication methods different from the authentication
2053+provided by the identity store backend. For example, this makes possible to
2054+use a SQL identity backend together with X.509 authentication, Kerberos, etc.
2055+instead of using the username/password combination.
2056+
2057+Using HTTPD authentication
2058+==========================
2059+
2060+Webservers like Apache HTTP support many methods of authentication. Keystone can
2061+profit from this feature and let the authentication be done in the webserver,
2062+that will pass down the authenticated user to Keystone using the ``REMOTE_USER``
2063+environment variable. This user must exist in advance in the identity backend
2064+so as to get a token from the controller.
2065+
2066+To use this method, Keystone should be running on :doc:`HTTPD <apache-httpd>`.
2067+
2068+X.509 example
2069+-------------
2070+
2071+The following snippet for the Apache conf will authenticate the user based on
2072+a valid X.509 certificate from a known CA::
2073+
2074+ <VirtualHost _default_:5000>
2075+ SSLEngine on
2076+ SSLCertificateFile /etc/ssl/certs/ssl.cert
2077+ SSLCertificateKeyFile /etc/ssl/private/ssl.key
2078+
2079+ SSLCACertificatePath /etc/ssl/allowed_cas
2080+ SSLCARevocationPath /etc/ssl/allowed_cas
2081+ SSLUserName SSL_CLIENT_S_DN_CN
2082+ SSLVerifyClient require
2083+ SSLVerifyDepth 10
2084+
2085+ (...)
2086+ </VirtualHost>
2087+
2088+Developing a WSGI middleware for authentication
2089+===============================================
2090+
2091+In addition to the method described above, it is possible to implement other
2092+custom authentication mechanisms using the ``REMOTE_USER`` WSGI environment
2093+variable.
2094+
2095+.. ATTENTION::
2096+ Please note that even if it is possible to develop a custom authentication
2097+ module, it is preferable to use the modules in the HTTPD server. Such
2098+ authentication modules in webservers like Apache have normally undergone
2099+ years of development and use in production systems and are actively maintained
2100+ upstream. Developing a custom authentication module that implements the same
2101+ authentication as an existing Apache module likely introduces a higher
2102+ security risk.
2103+
2104+If you find you must implement a custom authentication mechanism, you will need
2105+to develop a custom WSGI middleware pipeline component. This middleware should
2106+set the environment variable ``REMOTE_USER`` to the authenticated username.
2107+Keystone then will assume that the user has been already authenticated upstream
2108+and will not try to authenticate it. However, as with HTTPD authentication, the
2109+user must exist in advance in the identity backend so that a proper token can
2110+be issued.
2111+
2112+Your code should set the ``REMOTE_USER`` if the user is properly authenticated,
2113+following the semantics below::
2114+
2115+ class MyMiddlewareAuth(wsgi.Middleware):
2116+ def __init__(self, *args, **kwargs):
2117+ super(MyMiddlewareAuth, self).__init__(*args, **kwargs)
2118+
2119+ def process_request(self, request):
2120+ if request.environ.get('REMOTE_USER', None) is not None:
2121+ # Assume that it is authenticated upstream
2122+ return self.application
2123+
2124+ if not self.is_auth_applicable(request):
2125+ # Not applicable
2126+ return self.application
2127+
2128+ username = self.do_auth(request):
2129+ if username is not None:
2130+ # User is authenticated
2131+ request.environ['REMOTE_USER'] = username
2132+ else:
2133+ # User is not authenticated
2134+ raise exception.Unauthorized("Invalid user")
2135+
2136+
2137+Pipeline configuration
2138+----------------------
2139+
2140+Once you have your WSGI middleware component developed you have to add it to
2141+your pipeline. The first step is to add the middleware to your configuration file.
2142+Assuming that your middleware module is ``keystone.middleware.MyMiddlewareAuth``,
2143+you can configure it in your ``keystone.conf`` as::
2144+
2145+ [filter:my_auth]
2146+ paste.filter_factory = keystone.middleware.MyMiddlewareAuth.factory
2147+
2148+The second step is to add your middleware to the pipeline. The exact place where
2149+you should place it will depend on your code (i.e. if you need for example that
2150+the request body is converted from JSON before perform the authentication you
2151+should place it after the ``json_body`` filter) but it should be set before the
2152+``public_service`` (for the ``public_api`` pipeline) or ``admin_service`` (for
2153+the ``admin_api`` pipeline), since they consume authentication.
2154+
2155+For example, if the original pipeline looks like this::
2156+
2157+ [pipeline:public_api]
2158+ pipeline = stats_monitoring url_normalize token_auth admin_token_auth xml_body json_body debug ec2_extension user_crud_extension public_service
2159+
2160+Your modified pipeline might then look like this::
2161+
2162+ [pipeline:public_api]
2163+ pipeline = stats_monitoring url_normalize token_auth admin_token_auth xml_body json_body my_auth debug ec2_extension user_crud_extension public_service
2164
2165=== modified file 'doc/source/index.rst'
2166--- doc/source/index.rst 2012-11-23 09:01:53 +0000
2167+++ doc/source/index.rst 2013-01-25 16:27:23 +0000
2168@@ -66,6 +66,7 @@
2169 middlewarearchitecture
2170 api_curl_examples
2171 apache-httpd
2172+ external-auth
2173
2174 Code Documentation
2175 ==================
2176
2177=== modified file 'doc/source/setup.rst'
2178--- doc/source/setup.rst 2012-03-16 11:19:40 +0000
2179+++ doc/source/setup.rst 2013-01-25 16:27:23 +0000
2180@@ -70,7 +70,7 @@
2181
2182 The first is the list of dependencies needed for running keystone, the second list includes dependencies used for active development and testing of keystone itself.
2183
2184-These depdendencies can be installed from PyPi_ using the python tool pip_.
2185+These dependencies can be installed from PyPi_ using the python tool pip_.
2186
2187 .. _PyPi: http://pypi.python.org/
2188 .. _pip: http://pypi.python.org/pypi/pip
2189
2190=== modified file 'keystone.egg-info/SOURCES.txt'
2191--- keystone.egg-info/SOURCES.txt 2012-11-23 09:01:53 +0000
2192+++ keystone.egg-info/SOURCES.txt 2013-01-25 16:27:23 +0000
2193@@ -26,6 +26,7 @@
2194 doc/source/configuration.rst
2195 doc/source/configuringservices.rst
2196 doc/source/developing.rst
2197+doc/source/external-auth.rst
2198 doc/source/index.rst
2199 doc/source/installing.rst
2200 doc/source/middlewarearchitecture.rst
2201@@ -81,7 +82,9 @@
2202 keystone/clean.py
2203 keystone/cli.py
2204 keystone/config.py
2205+keystone/controllers.py
2206 keystone/exception.py
2207+keystone/routers.py
2208 keystone/service.py
2209 keystone/test.py
2210 keystone.egg-info/PKG-INFO
2211@@ -91,7 +94,9 @@
2212 keystone.egg-info/requires.txt
2213 keystone.egg-info/top_level.txt
2214 keystone/catalog/__init__.py
2215+keystone/catalog/controllers.py
2216 keystone/catalog/core.py
2217+keystone/catalog/routers.py
2218 keystone/catalog/backends/__init__.py
2219 keystone/catalog/backends/kvs.py
2220 keystone/catalog/backends/sql.py
2221@@ -100,12 +105,14 @@
2222 keystone/common/bufferedhttp.py
2223 keystone/common/cms.py
2224 keystone/common/controller.py
2225+keystone/common/dependency.py
2226 keystone/common/kvs.py
2227 keystone/common/logging.py
2228 keystone/common/manager.py
2229 keystone/common/models.py
2230 keystone/common/openssl.py
2231 keystone/common/policy.py
2232+keystone/common/router.py
2233 keystone/common/serializer.py
2234 keystone/common/systemd.py
2235 keystone/common/utils.py
2236@@ -127,13 +134,19 @@
2237 keystone/common/sql/migrate_repo/versions/002_sqlite_downgrade.sql
2238 keystone/common/sql/migrate_repo/versions/002_sqlite_upgrade.sql
2239 keystone/common/sql/migrate_repo/versions/002_token_id_hash.py
2240-keystone/common/sql/migrate_repo/versions/003_sqlite_downgrade.sql
2241 keystone/common/sql/migrate_repo/versions/003_sqlite_upgrade.sql
2242 keystone/common/sql/migrate_repo/versions/003_token_valid.py
2243 keystone/common/sql/migrate_repo/versions/004_undo_token_id_hash.py
2244 keystone/common/sql/migrate_repo/versions/005_set_utf8_character_set.py
2245 keystone/common/sql/migrate_repo/versions/006_add_policy_table.py
2246 keystone/common/sql/migrate_repo/versions/007_add_domain_tables.py
2247+keystone/common/sql/migrate_repo/versions/008_normalize_identity.py
2248+keystone/common/sql/migrate_repo/versions/008_sqlite_downgrade.sql
2249+keystone/common/sql/migrate_repo/versions/009_normalize_identity_migration.py
2250+keystone/common/sql/migrate_repo/versions/010_endpoints_v3.py
2251+keystone/common/sql/migrate_repo/versions/011_populate_endpoint_type.py
2252+keystone/common/sql/migrate_repo/versions/012_drop_legacy_endpoints.py
2253+keystone/common/sql/migrate_repo/versions/013_add_group_tables.py
2254 keystone/common/sql/migrate_repo/versions/__init__.py
2255 keystone/contrib/__init__.py
2256 keystone/contrib/admin_crud/__init__.py
2257@@ -152,7 +165,9 @@
2258 keystone/contrib/user_crud/__init__.py
2259 keystone/contrib/user_crud/core.py
2260 keystone/identity/__init__.py
2261+keystone/identity/controllers.py
2262 keystone/identity/core.py
2263+keystone/identity/routers.py
2264 keystone/identity/backends/__init__.py
2265 keystone/identity/backends/kvs.py
2266 keystone/identity/backends/pam.py
2267@@ -161,13 +176,13 @@
2268 keystone/identity/backends/ldap/core.py
2269 keystone/locale/keystone.pot
2270 keystone/locale/ca/LC_MESSAGES/keystone.po
2271+keystone/locale/hu/LC_MESSAGES/keystone.po
2272 keystone/locale/ja/LC_MESSAGES/keystone.po
2273 keystone/middleware/__init__.py
2274 keystone/middleware/auth_token.py
2275 keystone/middleware/core.py
2276 keystone/middleware/ec2_token.py
2277 keystone/middleware/s3_token.py
2278-keystone/middleware/swift_auth.py
2279 keystone/openstack/__init__.py
2280 keystone/openstack/common/README
2281 keystone/openstack/common/__init__.py
2282@@ -178,12 +193,16 @@
2283 keystone/openstack/common/setup.py
2284 keystone/openstack/common/timeutils.py
2285 keystone/policy/__init__.py
2286+keystone/policy/controllers.py
2287 keystone/policy/core.py
2288+keystone/policy/routers.py
2289 keystone/policy/backends/__init__.py
2290 keystone/policy/backends/rules.py
2291 keystone/policy/backends/sql.py
2292 keystone/token/__init__.py
2293+keystone/token/controllers.py
2294 keystone/token/core.py
2295+keystone/token/routers.py
2296 keystone/token/backends/__init__.py
2297 keystone/token/backends/kvs.py
2298 keystone/token/backends/memcache.py
2299@@ -203,6 +222,7 @@
2300 tests/legacy_essex.mysql
2301 tests/legacy_essex.sqlite
2302 tests/policy.json
2303+tests/test_auth.py
2304 tests/test_auth_token_middleware.py
2305 tests/test_backend.py
2306 tests/test_backend_kvs.py
2307@@ -213,8 +233,11 @@
2308 tests/test_backend_templated.py
2309 tests/test_cert_setup.py
2310 tests/test_content_types.py
2311+tests/test_contrib_s3_core.py
2312+tests/test_drivers.py
2313 tests/test_exception.py
2314 tests/test_import_legacy.py
2315+tests/test_injection.py
2316 tests/test_keystoneclient.py
2317 tests/test_keystoneclient_sql.py
2318 tests/test_middleware.py
2319@@ -223,12 +246,10 @@
2320 tests/test_policy.py
2321 tests/test_s3_token_middleware.py
2322 tests/test_serializer.py
2323-tests/test_service.py
2324 tests/test_setup.py
2325 tests/test_singular_plural.py
2326 tests/test_sql_upgrade.py
2327 tests/test_ssl.py
2328-tests/test_swift_auth_middleware.py
2329 tests/test_url_middleware.py
2330 tests/test_utils.py
2331 tests/test_v3.py
2332@@ -238,6 +259,7 @@
2333 tests/test_versions.py
2334 tests/test_wsgi.py
2335 tools/convert_to_sqlite.sh
2336+tools/flakes.py
2337 tools/install_venv.py
2338 tools/pip-requires
2339 tools/sample_data.sh
2340
2341=== modified file 'keystone.egg-info/requires.txt'
2342--- keystone.egg-info/requires.txt 2012-11-23 09:01:53 +0000
2343+++ keystone.egg-info/requires.txt 2013-01-25 16:27:23 +0000
2344@@ -1,5 +1,5 @@
2345 pam==0.1.4
2346-WebOb==1.0.8
2347+WebOb==1.2.3
2348 eventlet
2349 greenlet
2350 PasteDeploy
2351
2352=== modified file 'keystone/catalog/__init__.py'
2353--- keystone/catalog/__init__.py 2012-03-16 11:19:40 +0000
2354+++ keystone/catalog/__init__.py 2013-01-25 16:27:23 +0000
2355@@ -15,3 +15,5 @@
2356 # under the License.
2357
2358 from keystone.catalog.core import *
2359+from keystone.catalog import controllers
2360+from keystone.catalog import routers
2361
2362=== modified file 'keystone/catalog/backends/sql.py'
2363--- keystone/catalog/backends/sql.py 2012-11-23 09:01:53 +0000
2364+++ keystone/catalog/backends/sql.py 2013-01-25 16:27:23 +0000
2365@@ -36,12 +36,14 @@
2366
2367 class Endpoint(sql.ModelBase, sql.DictBase):
2368 __tablename__ = 'endpoint'
2369- attributes = ['id', 'region', 'service_id']
2370+ attributes = ['id', 'interface', 'region', 'service_id', 'url']
2371 id = sql.Column(sql.String(64), primary_key=True)
2372+ interface = sql.Column(sql.String(8), primary_key=True)
2373 region = sql.Column('region', sql.String(255))
2374 service_id = sql.Column(sql.String(64),
2375 sql.ForeignKey('service.id'),
2376 nullable=False)
2377+ url = sql.Column(sql.Text())
2378 extra = sql.Column(sql.JsonBlob())
2379
2380
2381@@ -88,7 +90,9 @@
2382 old_dict = ref.to_dict()
2383 old_dict.update(service_ref)
2384 new_service = Service.from_dict(old_dict)
2385- ref.type = new_service.type
2386+ for attr in Service.attributes:
2387+ if attr != 'id':
2388+ setattr(ref, attr, getattr(new_service, attr))
2389 ref.extra = new_service.extra
2390 session.flush()
2391 return ref.to_dict()
2392@@ -132,8 +136,9 @@
2393 old_dict = ref.to_dict()
2394 old_dict.update(endpoint_ref)
2395 new_endpoint = Endpoint.from_dict(old_dict)
2396- ref.service_id = new_endpoint.service_id
2397- ref.region = new_endpoint.region
2398+ for attr in Endpoint.attributes:
2399+ if attr != 'id':
2400+ setattr(ref, attr, getattr(new_endpoint, attr))
2401 ref.extra = new_endpoint.extra
2402 session.flush()
2403 return ref.to_dict()
2404@@ -142,25 +147,28 @@
2405 d = dict(CONF.iteritems())
2406 d.update({'tenant_id': tenant_id,
2407 'user_id': user_id})
2408+
2409 catalog = {}
2410-
2411- endpoints = self.list_endpoints()
2412- for ep in endpoints:
2413- service = self.get_service(ep['service_id'])
2414- srv_type = service['type']
2415- srv_name = service['name']
2416- region = ep['region']
2417-
2418- if region not in catalog:
2419- catalog[region] = {}
2420-
2421- catalog[region][srv_type] = {}
2422-
2423- srv_type = catalog[region][srv_type]
2424- srv_type['id'] = ep['id']
2425- srv_type['name'] = srv_name
2426- srv_type['publicURL'] = core.format_url(ep.get('publicurl', ''), d)
2427- srv_type['internalURL'] = core.format_url(ep.get('internalurl'), d)
2428- srv_type['adminURL'] = core.format_url(ep.get('adminurl'), d)
2429+ services = {}
2430+ for endpoint in self.list_endpoints():
2431+ # look up the service
2432+ services.setdefault(
2433+ endpoint['service_id'],
2434+ self.get_service(endpoint['service_id']))
2435+ service = services[endpoint['service_id']]
2436+
2437+ # add the endpoint to the catalog if it's not already there
2438+ catalog.setdefault(endpoint['region'], {})
2439+ catalog[endpoint['region']].setdefault(
2440+ service['type'], {
2441+ 'id': endpoint['id'],
2442+ 'name': service['name'],
2443+ 'publicURL': '', # this may be overridden, but must exist
2444+ })
2445+
2446+ # add the interface's url
2447+ url = core.format_url(endpoint.get('url'), d)
2448+ interface_url = '%sURL' % endpoint['interface']
2449+ catalog[endpoint['region']][service['type']][interface_url] = url
2450
2451 return catalog
2452
2453=== modified file 'keystone/catalog/backends/templated.py'
2454--- keystone/catalog/backends/templated.py 2012-11-02 13:48:49 +0000
2455+++ keystone/catalog/backends/templated.py 2013-01-25 16:27:23 +0000
2456@@ -106,7 +106,7 @@
2457 try:
2458 self.templates = parse_templates(open(template_file))
2459 except IOError:
2460- LOG.critical('Unable to open template file %s' % template_file)
2461+ LOG.critical(_('Unable to open template file %s') % template_file)
2462 raise
2463
2464 def get_catalog(self, user_id, tenant_id, metadata=None):
2465
2466=== added file 'keystone/catalog/controllers.py'
2467--- keystone/catalog/controllers.py 1970-01-01 00:00:00 +0000
2468+++ keystone/catalog/controllers.py 2013-01-25 16:27:23 +0000
2469@@ -0,0 +1,184 @@
2470+# vim: tabstop=4 shiftwidth=4 softtabstop=4
2471+
2472+# Copyright 2012 OpenStack LLC
2473+# Copyright 2012 Canonical Ltd.
2474+#
2475+# Licensed under the Apache License, Version 2.0 (the "License"); you may
2476+# not use this file except in compliance with the License. You may obtain
2477+# a copy of the License at
2478+#
2479+# http://www.apache.org/licenses/LICENSE-2.0
2480+#
2481+# Unless required by applicable law or agreed to in writing, software
2482+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
2483+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
2484+# License for the specific language governing permissions and limitations
2485+# under the License.
2486+
2487+import uuid
2488+
2489+from keystone.common import controller
2490+from keystone.common import dependency
2491+from keystone import exception
2492+
2493+
2494+INTERFACES = ['public', 'internal', 'admin']
2495+
2496+
2497+@dependency.requires('catalog_api')
2498+class Service(controller.V2Controller):
2499+ def get_services(self, context):
2500+ self.assert_admin(context)
2501+ service_list = self.catalog_api.list_services(context)
2502+ return {'OS-KSADM:services': service_list}
2503+
2504+ def get_service(self, context, service_id):
2505+ self.assert_admin(context)
2506+ service_ref = self.catalog_api.get_service(context, service_id)
2507+ return {'OS-KSADM:service': service_ref}
2508+
2509+ def delete_service(self, context, service_id):
2510+ self.assert_admin(context)
2511+ self.catalog_api.delete_service(context, service_id)
2512+
2513+ def create_service(self, context, OS_KSADM_service):
2514+ self.assert_admin(context)
2515+ service_id = uuid.uuid4().hex
2516+ service_ref = OS_KSADM_service.copy()
2517+ service_ref['id'] = service_id
2518+ new_service_ref = self.catalog_api.create_service(
2519+ context, service_id, service_ref)
2520+ return {'OS-KSADM:service': new_service_ref}
2521+
2522+
2523+@dependency.requires('catalog_api')
2524+class Endpoint(controller.V2Controller):
2525+ def get_endpoints(self, context):
2526+ """Merge matching v3 endpoint refs into legacy refs."""
2527+ self.assert_admin(context)
2528+ legacy_endpoints = {}
2529+ for endpoint in self.catalog_api.list_endpoints(context):
2530+ if not endpoint['legacy_endpoint_id']:
2531+ # endpoints created in v3 should not appear on the v2 API
2532+ continue
2533+
2534+ # is this is a legacy endpoint we haven't indexed yet?
2535+ if endpoint['legacy_endpoint_id'] not in legacy_endpoints:
2536+ legacy_ep = endpoint.copy()
2537+ legacy_ep['id'] = legacy_ep.pop('legacy_endpoint_id')
2538+ legacy_ep.pop('interface')
2539+ legacy_ep.pop('url')
2540+
2541+ legacy_endpoints[endpoint['legacy_endpoint_id']] = legacy_ep
2542+ else:
2543+ legacy_ep = legacy_endpoints[endpoint['legacy_endpoint_id']]
2544+
2545+ # add the legacy endpoint with an interface url
2546+ legacy_ep['%surl' % endpoint['interface']] = endpoint['url']
2547+ return {'endpoints': legacy_endpoints.values()}
2548+
2549+ def create_endpoint(self, context, endpoint):
2550+ """Create three v3 endpoint refs based on a legacy ref."""
2551+ self.assert_admin(context)
2552+
2553+ legacy_endpoint_ref = endpoint.copy()
2554+
2555+ urls = dict((i, endpoint.pop('%surl' % i)) for i in INTERFACES)
2556+ legacy_endpoint_id = uuid.uuid4().hex
2557+ for interface, url in urls.iteritems():
2558+ endpoint_ref = endpoint.copy()
2559+ endpoint_ref['id'] = uuid.uuid4().hex
2560+ endpoint_ref['legacy_endpoint_id'] = legacy_endpoint_id
2561+ endpoint_ref['interface'] = interface
2562+ endpoint_ref['url'] = url
2563+
2564+ self.catalog_api.create_endpoint(
2565+ context, endpoint_ref['id'], endpoint_ref)
2566+
2567+ legacy_endpoint_ref['id'] = legacy_endpoint_id
2568+ return {'endpoint': legacy_endpoint_ref}
2569+
2570+ def delete_endpoint(self, context, endpoint_id):
2571+ """Delete up to three v3 endpoint refs based on a legacy ref ID."""
2572+ self.assert_admin(context)
2573+
2574+ deleted_at_least_one = False
2575+ for endpoint in self.catalog_api.list_endpoints(context):
2576+ if endpoint['legacy_endpoint_id'] == endpoint_id:
2577+ self.catalog_api.delete_endpoint(context, endpoint['id'])
2578+ deleted_at_least_one = True
2579+
2580+ if not deleted_at_least_one:
2581+ raise exception.EndpointNotFound(endpoint_id=endpoint_id)
2582+
2583+
2584+@dependency.requires('catalog_api')
2585+class ServiceV3(controller.V3Controller):
2586+ @controller.protected
2587+ def create_service(self, context, service):
2588+ ref = self._assign_unique_id(self._normalize_dict(service))
2589+ self._require_attribute(ref, 'type')
2590+
2591+ ref = self.catalog_api.create_service(context, ref['id'], ref)
2592+ return {'service': ref}
2593+
2594+ @controller.protected
2595+ def list_services(self, context):
2596+ refs = self.catalog_api.list_services(context)
2597+ refs = self._filter_by_attribute(context, refs, 'type')
2598+ return {'services': self._paginate(context, refs)}
2599+
2600+ @controller.protected
2601+ def get_service(self, context, service_id):
2602+ ref = self.catalog_api.get_service(context, service_id)
2603+ return {'service': ref}
2604+
2605+ @controller.protected
2606+ def update_service(self, context, service_id, service):
2607+ self._require_matching_id(service_id, service)
2608+
2609+ ref = self.catalog_api.update_service(context, service_id, service)
2610+ return {'service': ref}
2611+
2612+ @controller.protected
2613+ def delete_service(self, context, service_id):
2614+ return self.catalog_api.delete_service(context, service_id)
2615+
2616+
2617+@dependency.requires('catalog_api')
2618+class EndpointV3(controller.V3Controller):
2619+ @controller.protected
2620+ def create_endpoint(self, context, endpoint):
2621+ ref = self._assign_unique_id(self._normalize_dict(endpoint))
2622+ self._require_attribute(ref, 'service_id')
2623+ self._require_attribute(ref, 'interface')
2624+ self.catalog_api.get_service(context, ref['service_id'])
2625+
2626+ ref = self.catalog_api.create_endpoint(context, ref['id'], ref)
2627+ return {'endpoint': ref}
2628+
2629+ @controller.protected
2630+ def list_endpoints(self, context):
2631+ refs = self.catalog_api.list_endpoints(context)
2632+ refs = self._filter_by_attribute(context, refs, 'service_id')
2633+ refs = self._filter_by_attribute(context, refs, 'interface')
2634+ return {'endpoints': self._paginate(context, refs)}
2635+
2636+ @controller.protected
2637+ def get_endpoint(self, context, endpoint_id):
2638+ ref = self.catalog_api.get_endpoint(context, endpoint_id)
2639+ return {'endpoint': ref}
2640+
2641+ @controller.protected
2642+ def update_endpoint(self, context, endpoint_id, endpoint):
2643+ self._require_matching_id(endpoint_id, endpoint)
2644+
2645+ if 'service_id' in endpoint:
2646+ self.catalog_api.get_service(context, endpoint['service_id'])
2647+
2648+ ref = self.catalog_api.update_endpoint(context, endpoint_id, endpoint)
2649+ return {'endpoint': ref}
2650+
2651+ @controller.protected
2652+ def delete_endpoint(self, context, endpoint_id):
2653+ return self.catalog_api.delete_endpoint(context, endpoint_id)
2654
2655=== modified file 'keystone/catalog/core.py'
2656--- keystone/catalog/core.py 2012-11-23 09:01:53 +0000
2657+++ keystone/catalog/core.py 2013-01-25 16:27:23 +0000
2658@@ -17,17 +17,11 @@
2659
2660 """Main entry point into the Catalog service."""
2661
2662-import uuid
2663-
2664-from keystone.common import controller
2665+from keystone.common import dependency
2666 from keystone.common import logging
2667 from keystone.common import manager
2668-from keystone.common import wsgi
2669 from keystone import config
2670 from keystone import exception
2671-from keystone import identity
2672-from keystone import policy
2673-from keystone import token
2674
2675
2676 CONF = config.CONF
2677@@ -41,21 +35,24 @@
2678 except AttributeError:
2679 return None
2680 except KeyError as e:
2681- LOG.error("Malformed endpoint %s - unknown key %s" %
2682- (url, str(e)))
2683+ LOG.error(_("Malformed endpoint %(url)s - unknown key %(keyerror)s") %
2684+ {"url": url,
2685+ "keyerror": str(e)})
2686 raise exception.MalformedEndpoint(endpoint=url)
2687 except TypeError as e:
2688- LOG.error("Malformed endpoint %s - type mismatch %s \
2689- (are you missing brackets ?)" %
2690- (url, str(e)))
2691+ LOG.error(_("Malformed endpoint %(url)s - unknown key %(keyerror)s"
2692+ "(are you missing brackets ?)") %
2693+ {"url": url,
2694+ "keyerror": str(e)})
2695 raise exception.MalformedEndpoint(endpoint=url)
2696 except ValueError as e:
2697- LOG.error("Malformed endpoint %s - incomplete format \
2698- (are you missing a type notifier ?)" % url)
2699+ LOG.error(_("Malformed endpoint %s - incomplete format \
2700+ (are you missing a type notifier ?)") % url)
2701 raise exception.MalformedEndpoint(endpoint=url)
2702 return result
2703
2704
2705+@dependency.provider('catalog_api')
2706 class Manager(manager.Manager):
2707 """Default pivot point for the Catalog backend.
2708
2709@@ -216,132 +213,3 @@
2710
2711 """
2712 raise exception.NotImplemented()
2713-
2714-
2715-class ServiceController(wsgi.Application):
2716- def __init__(self):
2717- self.catalog_api = Manager()
2718- self.identity_api = identity.Manager()
2719- self.policy_api = policy.Manager()
2720- self.token_api = token.Manager()
2721- super(ServiceController, self).__init__()
2722-
2723- def get_services(self, context):
2724- self.assert_admin(context)
2725- service_list = self.catalog_api.list_services(context)
2726- return {'OS-KSADM:services': service_list}
2727-
2728- def get_service(self, context, service_id):
2729- self.assert_admin(context)
2730- service_ref = self.catalog_api.get_service(context, service_id)
2731- return {'OS-KSADM:service': service_ref}
2732-
2733- def delete_service(self, context, service_id):
2734- self.assert_admin(context)
2735- self.catalog_api.delete_service(context, service_id)
2736-
2737- def create_service(self, context, OS_KSADM_service):
2738- self.assert_admin(context)
2739- service_id = uuid.uuid4().hex
2740- service_ref = OS_KSADM_service.copy()
2741- service_ref['id'] = service_id
2742- new_service_ref = self.catalog_api.create_service(
2743- context, service_id, service_ref)
2744- return {'OS-KSADM:service': new_service_ref}
2745-
2746-
2747-class EndpointController(wsgi.Application):
2748- def __init__(self):
2749- self.catalog_api = Manager()
2750- self.identity_api = identity.Manager()
2751- self.policy_api = policy.Manager()
2752- self.token_api = token.Manager()
2753- super(EndpointController, self).__init__()
2754-
2755- def get_endpoints(self, context):
2756- self.assert_admin(context)
2757- endpoint_list = self.catalog_api.list_endpoints(context)
2758- return {'endpoints': endpoint_list}
2759-
2760- def create_endpoint(self, context, endpoint):
2761- self.assert_admin(context)
2762- endpoint_id = uuid.uuid4().hex
2763- endpoint_ref = endpoint.copy()
2764- endpoint_ref['id'] = endpoint_id
2765- new_endpoint_ref = self.catalog_api.create_endpoint(
2766- context, endpoint_id, endpoint_ref)
2767- return {'endpoint': new_endpoint_ref}
2768-
2769- def delete_endpoint(self, context, endpoint_id):
2770- self.assert_admin(context)
2771- self.catalog_api.delete_endpoint(context, endpoint_id)
2772-
2773-
2774-class ServiceControllerV3(controller.V3Controller):
2775- @controller.protected
2776- def create_service(self, context, service):
2777- ref = self._assign_unique_id(self._normalize_dict(service))
2778- self._require_attribute(ref, 'type')
2779-
2780- ref = self.catalog_api.create_service(context, ref['id'], ref)
2781- return {'service': ref}
2782-
2783- @controller.protected
2784- def list_services(self, context):
2785- refs = self.catalog_api.list_services(context)
2786- refs = self._filter_by_attribute(context, refs, 'type')
2787- return {'services': self._paginate(context, refs)}
2788-
2789- @controller.protected
2790- def get_service(self, context, service_id):
2791- ref = self.catalog_api.get_service(context, service_id)
2792- return {'service': ref}
2793-
2794- @controller.protected
2795- def update_service(self, context, service_id, service):
2796- self._require_matching_id(service_id, service)
2797-
2798- ref = self.catalog_api.update_service(context, service_id, service)
2799- return {'service': ref}
2800-
2801- @controller.protected
2802- def delete_service(self, context, service_id):
2803- return self.catalog_api.delete_service(context, service_id)
2804-
2805-
2806-class EndpointControllerV3(controller.V3Controller):
2807- @controller.protected
2808- def create_endpoint(self, context, endpoint):
2809- ref = self._assign_unique_id(self._normalize_dict(endpoint))
2810- self._require_attribute(ref, 'service_id')
2811- self._require_attribute(ref, 'interface')
2812- self.catalog_api.get_service(context, ref['service_id'])
2813-
2814- ref = self.catalog_api.create_endpoint(context, ref['id'], ref)
2815- return {'endpoint': ref}
2816-
2817- @controller.protected
2818- def list_endpoints(self, context):
2819- refs = self.catalog_api.list_endpoints(context)
2820- refs = self._filter_by_attribute(context, refs, 'service_id')
2821- refs = self._filter_by_attribute(context, refs, 'interface')
2822- return {'endpoints': self._paginate(context, refs)}
2823-
2824- @controller.protected
2825- def get_endpoint(self, context, endpoint_id):
2826- ref = self.catalog_api.get_endpoint(context, endpoint_id)
2827- return {'endpoint': ref}
2828-
2829- @controller.protected
2830- def update_endpoint(self, context, endpoint_id, endpoint):
2831- self._require_matching_id(endpoint_id, endpoint)
2832-
2833- if 'service_id' in endpoint:
2834- self.catalog_api.get_service(context, endpoint['service_id'])
2835-
2836- ref = self.catalog_api.update_endpoint(context, endpoint_id, endpoint)
2837- return {'endpoint': ref}
2838-
2839- @controller.protected
2840- def delete_endpoint(self, context, endpoint_id):
2841- return self.catalog_api.delete_endpoint(context, endpoint_id)
2842
2843=== added file 'keystone/catalog/routers.py'
2844--- keystone/catalog/routers.py 1970-01-01 00:00:00 +0000
2845+++ keystone/catalog/routers.py 2013-01-25 16:27:23 +0000
2846@@ -0,0 +1,25 @@
2847+# vim: tabstop=4 shiftwidth=4 softtabstop=4
2848+
2849+# Copyright 2012 OpenStack LLC
2850+#
2851+# Licensed under the Apache License, Version 2.0 (the "License"); you may
2852+# not use this file except in compliance with the License. You may obtain
2853+# a copy of the License at
2854+#
2855+# http://www.apache.org/licenses/LICENSE-2.0
2856+#
2857+# Unless required by applicable law or agreed to in writing, software
2858+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
2859+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
2860+# License for the specific language governing permissions and limitations
2861+# under the License.
2862+
2863+from keystone.catalog import controllers
2864+from keystone.common import router
2865+
2866+
2867+def append_v3_routers(mapper, routers):
2868+ routers.append(router.Router(controllers.ServiceV3(),
2869+ 'services', 'service'))
2870+ routers.append(router.Router(controllers.EndpointV3(),
2871+ 'endpoints', 'endpoint'))
2872
2873=== modified file 'keystone/clean.py'
2874--- keystone/clean.py 2012-11-23 09:01:53 +0000
2875+++ keystone/clean.py 2013-01-25 16:27:23 +0000
2876@@ -20,20 +20,21 @@
2877 def check_length(property_name, value, min_length=1, max_length=64):
2878 if len(value) < min_length:
2879 if min_length == 1:
2880- msg = "%s cannot be empty." % property_name
2881+ msg = _("%s cannot be empty.") % property_name
2882 else:
2883- msg = ("%(property_name)s cannot be less than "
2884- "%(min_length)s characters.") % locals()
2885+ msg = (_("%(property_name)s cannot be less than "
2886+ "%(min_length)s characters.")) % locals()
2887 raise exception.ValidationError(msg)
2888 if len(value) > max_length:
2889- msg = ("%(property_name)s should not be greater than "
2890- "%(max_length)s characters.") % locals()
2891+ msg = (_("%(property_name)s should not be greater than "
2892+ "%(max_length)s characters.")) % locals()
2893 raise exception.ValidationError(msg)
2894
2895
2896 def check_type(property_name, value, expected_type, display_expected_type):
2897 if not isinstance(value, expected_type):
2898- msg = "%(property_name)s is not a %(display_expected_type)s" % locals()
2899+ msg = _("%(property_name)s is not a"
2900+ "%(display_expected_type)s") % locals()
2901 raise exception.ValidationError(msg)
2902
2903
2904@@ -54,3 +55,7 @@
2905
2906 def user_name(name):
2907 return check_name('User', name)
2908+
2909+
2910+def group_name(name):
2911+ return check_name('Group', name)
2912
2913=== modified file 'keystone/cli.py'
2914--- keystone/cli.py 2012-07-06 10:37:01 +0000
2915+++ keystone/cli.py 2013-01-25 16:27:23 +0000
2916@@ -16,11 +16,9 @@
2917
2918 from __future__ import absolute_import
2919
2920-import sys
2921-import textwrap
2922-
2923 from keystone import config
2924 from keystone.common import openssl
2925+from keystone.openstack.common import cfg
2926 from keystone.openstack.common import importutils
2927 from keystone.openstack.common import jsonutils
2928
2929@@ -28,17 +26,14 @@
2930
2931
2932 class BaseApp(object):
2933- def __init__(self, argv=None):
2934- self.argv = argv
2935-
2936- def run(self):
2937- return self.main()
2938-
2939- def missing_param(self, param):
2940- print 'Missing parameter: %s' % param
2941- CONF.print_help()
2942- print_commands(CMDS)
2943- sys.exit(1)
2944+
2945+ name = None
2946+
2947+ @classmethod
2948+ def add_argument_parser(cls, subparsers):
2949+ parser = subparsers.add_parser(cls.name, help=cls.__doc__)
2950+ parser.set_defaults(cmd_class=cls)
2951+ return parser
2952
2953
2954 class DbSync(BaseApp):
2955@@ -46,10 +41,8 @@
2956
2957 name = 'db_sync'
2958
2959- def __init__(self, *args, **kw):
2960- super(DbSync, self).__init__(*args, **kw)
2961-
2962- def main(self):
2963+ @staticmethod
2964+ def main():
2965 for k in ['identity', 'catalog', 'policy', 'token']:
2966 driver = importutils.import_object(getattr(CONF, k).driver)
2967 if hasattr(driver, 'db_sync'):
2968@@ -61,10 +54,8 @@
2969
2970 name = 'pki_setup'
2971
2972- def __init__(self, *args, **kw):
2973- super(PKISetup, self).__init__(*args, **kw)
2974-
2975- def main(self):
2976+ @staticmethod
2977+ def main():
2978 conf_ssl = openssl.ConfigurePKI()
2979 conf_ssl.run()
2980
2981@@ -74,15 +65,16 @@
2982
2983 name = 'import_legacy'
2984
2985- def __init__(self, *args, **kw):
2986- super(ImportLegacy, self).__init__(*args, **kw)
2987+ @classmethod
2988+ def add_argument_parser(cls, subparsers):
2989+ parser = super(ImportLegacy, cls).add_argument_parser(subparsers)
2990+ parser.add_argument('old_db')
2991+ return parser
2992
2993- def main(self):
2994+ @staticmethod
2995+ def main():
2996 from keystone.common.sql import legacy
2997- if len(self.argv) < 2:
2998- return self.missing_param('old_db')
2999- old_db = self.argv[1]
3000- migration = legacy.LegacyMigration(old_db)
3001+ migration = legacy.LegacyMigration(CONF.command.old_db)
3002 migration.migrate_all()
3003
3004
3005@@ -91,15 +83,17 @@
3006
3007 name = 'export_legacy_catalog'
3008
3009- def __init__(self, *args, **kw):
3010- super(ExportLegacyCatalog, self).__init__(*args, **kw)
3011+ @classmethod
3012+ def add_argument_parser(cls, subparsers):
3013+ parser = super(ExportLegacyCatalog,
3014+ cls).add_argument_parser(subparsers)
3015+ parser.add_argument('old_db')
3016+ return parser
3017
3018- def main(self):
3019+ @staticmethod
3020+ def main():
3021 from keystone.common.sql import legacy
3022- if len(self.argv) < 2:
3023- return self.missing_param('old_db')
3024- old_db = self.argv[1]
3025- migration = legacy.LegacyMigration(old_db)
3026+ migration = legacy.LegacyMigration(CONF.command.old_db)
3027 print '\n'.join(migration.dump_catalog())
3028
3029
3030@@ -108,60 +102,43 @@
3031
3032 name = 'import_nova_auth'
3033
3034- def __init__(self, *args, **kw):
3035- super(ImportNovaAuth, self).__init__(*args, **kw)
3036+ @classmethod
3037+ def add_argument_parser(cls, subparsers):
3038+ parser = super(ImportNovaAuth, cls).add_argument_parser(subparsers)
3039+ parser.add_argument('dump_file')
3040+ return parser
3041
3042- def main(self):
3043+ @staticmethod
3044+ def main():
3045 from keystone.common.sql import nova
3046- if len(self.argv) < 2:
3047- return self.missing_param('dump_file')
3048- dump_file = self.argv[1]
3049- dump_data = jsonutils.loads(open(dump_file).read())
3050+ dump_data = jsonutils.loads(open(CONF.command.dump_file).read())
3051 nova.import_auth(dump_data)
3052
3053
3054-CMDS = {'db_sync': DbSync,
3055- 'import_legacy': ImportLegacy,
3056- 'export_legacy_catalog': ExportLegacyCatalog,
3057- 'import_nova_auth': ImportNovaAuth,
3058- 'pki_setup': PKISetup,
3059- }
3060-
3061-
3062-def print_commands(cmds):
3063- print
3064- print 'Available commands:'
3065- o = []
3066- max_length = max([len(k) for k in cmds]) + 2
3067- for k, cmd in sorted(cmds.iteritems()):
3068- initial_indent = '%s%s: ' % (' ' * (max_length - len(k)), k)
3069- tw = textwrap.TextWrapper(initial_indent=initial_indent,
3070- subsequent_indent=' ' * (max_length + 2),
3071- width=80)
3072- o.extend(tw.wrap(
3073- (cmd.__doc__ and cmd.__doc__ or 'no docs').strip().split('\n')[0]))
3074- print '\n'.join(o)
3075-
3076-
3077-def run(cmd, args):
3078- return CMDS[cmd](argv=args).run()
3079+CMDS = [
3080+ DbSync,
3081+ ExportLegacyCatalog,
3082+ ImportLegacy,
3083+ ImportNovaAuth,
3084+ PKISetup,
3085+]
3086+
3087+
3088+def add_command_parsers(subparsers):
3089+ for cmd in CMDS:
3090+ cmd.add_argument_parser(subparsers)
3091+
3092+
3093+command_opt = cfg.SubCommandOpt('command',
3094+ title='Commands',
3095+ help='Available commands',
3096+ handler=add_command_parsers)
3097
3098
3099 def main(argv=None, config_files=None):
3100- CONF.reset()
3101- args = CONF(args=argv,
3102- project='keystone',
3103- usage='%prog COMMAND',
3104- default_config_files=config_files)
3105-
3106- if len(args) < 2:
3107- CONF.print_help()
3108- print_commands(CMDS)
3109- sys.exit(1)
3110-
3111- cmd = args[1]
3112- if cmd in CMDS:
3113- return run(cmd, (args[:1] + args[2:]))
3114- else:
3115- print_commands(CMDS)
3116- sys.exit("Unknown command: %s" % cmd)
3117+ CONF.register_cli_opt(command_opt)
3118+ CONF(args=argv[1:],
3119+ project='keystone',
3120+ usage='%(prog)s [' + '|'.join([cmd.name for cmd in CMDS]) + ']',
3121+ default_config_files=config_files)
3122+ CONF.command.cmd_class.main()
3123
3124=== modified file 'keystone/common/bufferedhttp.py'
3125--- keystone/common/bufferedhttp.py 2012-11-23 09:01:53 +0000
3126+++ keystone/common/bufferedhttp.py 2013-01-25 16:27:23 +0000
3127@@ -99,8 +99,8 @@
3128
3129 def getresponse(self):
3130 response = HTTPConnection.getresponse(self)
3131- LOG.debug('HTTP PERF: %(time).5f seconds to %(method)s '
3132- '%(host)s:%(port)s %(path)s)',
3133+ LOG.debug(_('HTTP PERF: %(time).5f seconds to %(method)s '
3134+ '%(host)s:%(port)s %(path)s)'),
3135 {'time': time.time() - self._connected_time,
3136 'method': self._method,
3137 'host': self.host,
3138
3139=== modified file 'keystone/common/cms.py'
3140--- keystone/common/cms.py 2012-11-23 09:01:53 +0000
3141+++ keystone/common/cms.py 2013-01-25 16:27:23 +0000
3142@@ -41,7 +41,7 @@
3143 output, err = process.communicate(formatted)
3144 retcode = process.poll()
3145 if retcode:
3146- LOG.error('Verify error: %s' % err)
3147+ LOG.error(_('Verify error: %s') % err)
3148 raise subprocess.CalledProcessError(retcode, "openssl", output=err)
3149 return output
3150
3151@@ -131,7 +131,7 @@
3152 output, err = process.communicate(text)
3153 retcode = process.poll()
3154 if retcode or "Error" in err:
3155- LOG.error('Signing error: %s' % err)
3156+ LOG.error(_('Signing error: %s') % err)
3157 raise subprocess.CalledProcessError(retcode, "openssl")
3158 return output
3159
3160
3161=== modified file 'keystone/common/controller.py'
3162--- keystone/common/controller.py 2012-11-23 09:01:53 +0000
3163+++ keystone/common/controller.py 2013-01-25 16:27:23 +0000
3164@@ -1,6 +1,7 @@
3165 import uuid
3166 import functools
3167
3168+from keystone.common import dependency
3169 from keystone.common import logging
3170 from keystone.common import wsgi
3171 from keystone import exception
3172@@ -17,15 +18,15 @@
3173 if not context['is_admin']:
3174 action = 'identity:%s' % f.__name__
3175
3176- LOG.debug('RBAC: Authorizing %s(%s)' % (
3177+ LOG.debug(_('RBAC: Authorizing %s(%s)' % (
3178 action,
3179- ', '.join(['%s=%s' % (k, kwargs[k]) for k in kwargs])))
3180+ ', '.join(['%s=%s' % (k, kwargs[k]) for k in kwargs]))))
3181
3182 try:
3183 token_ref = self.token_api.get_token(
3184 context=context, token_id=context['token_id'])
3185 except exception.TokenNotFound:
3186- LOG.warning('RBAC: Invalid token')
3187+ LOG.warning(_('RBAC: Invalid token'))
3188 raise exception.Unauthorized()
3189
3190 creds = token_ref['metadata'].copy()
3191@@ -33,13 +34,13 @@
3192 try:
3193 creds['user_id'] = token_ref['user'].get('id')
3194 except AttributeError:
3195- LOG.warning('RBAC: Invalid user')
3196+ LOG.warning(_('RBAC: Invalid user'))
3197 raise exception.Unauthorized()
3198
3199 try:
3200 creds['tenant_id'] = token_ref['tenant'].get('id')
3201 except AttributeError:
3202- LOG.debug('RBAC: Proceeding without tenant')
3203+ LOG.debug(_('RBAC: Proceeding without tenant'))
3204
3205 # NOTE(vish): this is pretty inefficient
3206 creds['roles'] = [self.identity_api.get_role(context, role)['name']
3207@@ -47,24 +48,23 @@
3208
3209 self.policy_api.enforce(context, creds, action, kwargs)
3210
3211- LOG.debug('RBAC: Authorization granted')
3212+ LOG.debug(_('RBAC: Authorization granted'))
3213 else:
3214- LOG.warning('RBAC: Bypassing authorization')
3215+ LOG.warning(_('RBAC: Bypassing authorization'))
3216
3217 return f(self, context, **kwargs)
3218 return wrapper
3219
3220
3221-class V3Controller(wsgi.Application):
3222+@dependency.requires('identity_api', 'policy_api', 'token_api')
3223+class V2Controller(wsgi.Application):
3224+ """Base controller class for Identity API v2."""
3225+ pass
3226+
3227+
3228+class V3Controller(V2Controller):
3229 """Base controller class for Identity API v3."""
3230
3231- def __init__(self, catalog_api, identity_api, token_api, policy_api):
3232- self.catalog_api = catalog_api
3233- self.identity_api = identity_api
3234- self.policy_api = policy_api
3235- self.token_api = token_api
3236- super(V3Controller, self).__init__()
3237-
3238 def _paginate(self, context, refs):
3239 """Paginates a list of references by page & per_page query strings."""
3240 page = context['query_string'].get('page', 1)
3241
3242=== added file 'keystone/common/dependency.py'
3243--- keystone/common/dependency.py 1970-01-01 00:00:00 +0000
3244+++ keystone/common/dependency.py 2013-01-25 16:27:23 +0000
3245@@ -0,0 +1,67 @@
3246+# vim: tabstop=4 shiftwidth=4 softtabstop=4
3247+
3248+# Copyright 2012 OpenStack LLC
3249+#
3250+# Licensed under the Apache License, Version 2.0 (the "License"); you may
3251+# not use this file except in compliance with the License. You may obtain
3252+# a copy of the License at
3253+#
3254+# http://www.apache.org/licenses/LICENSE-2.0
3255+#
3256+# Unless required by applicable law or agreed to in writing, software
3257+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
3258+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
3259+# License for the specific language governing permissions and limitations
3260+# under the License.
3261+
3262+REGISTRY = {}
3263+
3264+
3265+class UnresolvableDependencyException(Exception):
3266+ def __init__(self, name):
3267+ msg = 'Unregistered dependency: %s' % name
3268+ super(UnresolvableDependencyException, self).__init__(msg)
3269+
3270+
3271+def provider(name):
3272+ """Register the wrapped dependency provider under the specified name."""
3273+ def wrapper(cls):
3274+ def wrapped(init):
3275+ def __wrapped_init__(self, *args, **kwargs):
3276+ """Initialize the wrapped object and add it to the registry."""
3277+ init(self, *args, **kwargs)
3278+ REGISTRY[name] = self
3279+
3280+ return __wrapped_init__
3281+
3282+ cls.__init__ = wrapped(cls.__init__)
3283+ return cls
3284+
3285+ return wrapper
3286+
3287+
3288+def requires(*dependencies):
3289+ """Inject specified dependencies from the registry into the instance."""
3290+ def wrapper(self, *args, **kwargs):
3291+ """Inject each dependency from the registry."""
3292+ self.__wrapped_init__(*args, **kwargs)
3293+
3294+ for dependency in self._dependencies:
3295+ if dependency not in REGISTRY:
3296+ raise UnresolvableDependencyException(dependency)
3297+ setattr(self, dependency, REGISTRY[dependency])
3298+
3299+ def wrapped(cls):
3300+ """Note the required dependencies on the object for later injection.
3301+
3302+ The dependencies of the parent class are combined with that of the
3303+ child class to create a new set of dependencies.
3304+ """
3305+ existing_dependencies = getattr(cls, '_dependencies', set())
3306+ cls._dependencies = existing_dependencies.union(dependencies)
3307+ if not hasattr(cls, '__wrapped_init__'):
3308+ cls.__wrapped_init__ = cls.__init__
3309+ cls.__init__ = wrapper
3310+ return cls
3311+
3312+ return wrapped
3313
3314=== modified file 'keystone/common/ldap/core.py'
3315--- keystone/common/ldap/core.py 2012-11-23 09:01:53 +0000
3316+++ keystone/common/ldap/core.py 2013-01-25 16:27:23 +0000
3317@@ -168,8 +168,8 @@
3318 pass
3319 else:
3320 raise exception.Conflict(type=self.options_name,
3321- details='Duplicate name, %s.' %
3322- values['name'])
3323+ details=_('Duplicate name, %s.') %
3324+ values['name'])
3325
3326 if values.get('id') is not None:
3327 try:
3328@@ -178,12 +178,13 @@
3329 pass
3330 else:
3331 raise exception.Conflict(type=self.options_name,
3332- details='Duplicate ID, %s.' %
3333- values['id'])
3334+ details=_('Duplicate ID, %s.') %
3335+ values['id'])
3336
3337 def create(self, values):
3338 if not self.allow_create:
3339- msg = 'LDAP backend does not allow %s create' % self.options_name
3340+ msg = _('LDAP backend does not allow %s create') \
3341+ % self.options_name
3342 raise exception.ForbiddenAction(msg)
3343
3344 conn = self.get_connection()
3345@@ -289,7 +290,8 @@
3346
3347 def update(self, id, values, old_obj=None):
3348 if not self.allow_update:
3349- msg = 'LDAP backend does not allow %s update' % self.options_name
3350+ msg = _('LDAP backend does not allow %s update') \
3351+ % self.options_name
3352 raise exception.ForbiddenAction(msg)
3353
3354 if old_obj is None:
3355@@ -316,7 +318,8 @@
3356
3357 def delete(self, id):
3358 if not self.allow_delete:
3359- msg = 'LDAP backend does not allow %s delete' % self.options_name
3360+ msg = _('LDAP backend does not allow %s delete') \
3361+ % self.options_name
3362 raise exception.ForbiddenAction(msg)
3363
3364 conn = self.get_connection()
3365@@ -333,11 +336,11 @@
3366
3367 class LdapWrapper(object):
3368 def __init__(self, url):
3369- LOG.debug("LDAP init: url=%s", url)
3370+ LOG.debug(_("LDAP init: url=%s", url))
3371 self.conn = ldap.initialize(url)
3372
3373 def simple_bind_s(self, user, password):
3374- LOG.debug("LDAP bind: dn=%s", user)
3375+ LOG.debug(_("LDAP bind: dn=%s", user))
3376 return self.conn.simple_bind_s(user, password)
3377
3378 def add_s(self, dn, attrs):
3379@@ -348,15 +351,15 @@
3380 if kind != 'userPassword'
3381 else ['****'])
3382 for kind, values in ldap_attrs]
3383- LOG.debug('LDAP add: dn=%s, attrs=%s', dn, sane_attrs)
3384+ LOG.debug(_('LDAP add: dn=%s, attrs=%s', dn, sane_attrs))
3385 return self.conn.add_s(dn, ldap_attrs)
3386
3387 def search_s(self, dn, scope, query):
3388 if LOG.isEnabledFor(logging.DEBUG):
3389- LOG.debug('LDAP search: dn=%s, scope=%s, query=%s',
3390+ LOG.debug(_('LDAP search: dn=%s, scope=%s, query=%s',
3391 dn,
3392 scope,
3393- query)
3394+ query))
3395 res = self.conn.search_s(dn, scope, query)
3396
3397 o = []
3398@@ -376,14 +379,14 @@
3399 sane_modlist = [(op, kind, (values if kind != 'userPassword'
3400 else ['****']))
3401 for op, kind, values in ldap_modlist]
3402- LOG.debug("LDAP modify: dn=%s, modlist=%s", dn, sane_modlist)
3403+ LOG.debug(_("LDAP modify: dn=%s, modlist=%s", dn, sane_modlist))
3404
3405 return self.conn.modify_s(dn, ldap_modlist)
3406
3407 def delete_s(self, dn):
3408- LOG.debug("LDAP delete: dn=%s", dn)
3409+ LOG.debug(_("LDAP delete: dn=%s", dn))
3410 return self.conn.delete_s(dn)
3411
3412 def delete_ext_s(self, dn, serverctrls):
3413- LOG.debug("LDAP delete_ext: dn=%s, serverctrls=%s", dn, serverctrls)
3414+ LOG.debug(_("LDAP delete_ext: dn=%s, serverctrls=%s", dn, serverctrls))
3415 return self.conn.delete_ext_s(dn, serverctrls)
3416
3417=== modified file 'keystone/common/ldap/fakeldap.py'
3418--- keystone/common/ldap/fakeldap.py 2012-11-02 13:48:49 +0000
3419+++ keystone/common/ldap/fakeldap.py 2013-01-25 16:27:23 +0000
3420@@ -145,7 +145,7 @@
3421 __prefix = 'ldap:'
3422
3423 def __init__(self, url):
3424- LOG.debug('FakeLdap initialize url=%s', url)
3425+ LOG.debug(_('FakeLdap initialize url=%s'), url)
3426 if url == 'fake://memory':
3427 self.db = FakeShelve.get_instance()
3428 else:
3429@@ -155,26 +155,27 @@
3430 """This method is ignored, but provided for compatibility."""
3431 if server_fail:
3432 raise ldap.SERVER_DOWN
3433- LOG.debug('FakeLdap bind dn=%s', dn)
3434+ LOG.debug(_('FakeLdap bind dn=%s'), dn)
3435 if dn == 'cn=Admin' and password == 'password':
3436 return
3437
3438 try:
3439 attrs = self.db['%s%s' % (self.__prefix, dn)]
3440 except KeyError:
3441- LOG.error('FakeLdap bind fail: dn=%s not found', dn)
3442+ LOG.error(_('FakeLdap bind fail: dn=%s not found'), dn)
3443 raise ldap.NO_SUCH_OBJECT
3444
3445 db_password = None
3446 try:
3447 db_password = attrs['userPassword'][0]
3448 except (KeyError, IndexError):
3449- LOG.error('FakeLdap bind fail: password for dn=%s not found', dn)
3450+ LOG.error(_('FakeLdap bind fail: password for dn=%s not found'),
3451+ dn)
3452 raise ldap.INAPPROPRIATE_AUTH
3453
3454 if not utils.ldap_check_password(password, db_password):
3455- LOG.error('FakeLdap bind fail: password for dn=%s does'
3456- ' not match' % dn)
3457+ LOG.error(_('FakeLdap bind fail: password for dn=%s does'
3458+ ' not match') % dn)
3459 raise ldap.INVALID_CREDENTIALS
3460
3461 def unbind_s(self):
3462@@ -188,10 +189,10 @@
3463 raise ldap.SERVER_DOWN
3464
3465 key = '%s%s' % (self.__prefix, dn)
3466- LOG.debug('FakeLdap add item: dn=%s, attrs=%s', dn, attrs)
3467+ LOG.debug(_('FakeLdap add item: dn=%s, attrs=%s'), dn, attrs)
3468 if key in self.db:
3469- LOG.error('FakeLdap add item failed: dn=%s is'
3470- ' already in store.', dn)
3471+ LOG.error(_('FakeLdap add item failed: dn=%s is'
3472+ ' already in store.'), dn)
3473 raise ldap.ALREADY_EXISTS(dn)
3474
3475 self.db[key] = dict([(k, v if isinstance(v, list) else [v])
3476@@ -204,11 +205,11 @@
3477 raise ldap.SERVER_DOWN
3478
3479 key = '%s%s' % (self.__prefix, dn)
3480- LOG.debug('FakeLdap delete item: dn=%s', dn)
3481+ LOG.debug(_('FakeLdap delete item: dn=%s'), dn)
3482 try:
3483 del self.db[key]
3484 except KeyError:
3485- LOG.error('FakeLdap delete item failed: dn=%s not found.', dn)
3486+ LOG.error(_('FakeLdap delete item failed: dn=%s not found.'), dn)
3487 raise ldap.NO_SUCH_OBJECT
3488 self.db.sync()
3489
3490@@ -218,11 +219,11 @@
3491 raise ldap.SERVER_DOWN
3492
3493 key = '%s%s' % (self.__prefix, dn)
3494- LOG.debug('FakeLdap delete item: dn=%s', dn)
3495+ LOG.debug(_('FakeLdap delete item: dn=%s'), dn)
3496 try:
3497 del self.db[key]
3498 except KeyError:
3499- LOG.error('FakeLdap delete item failed: dn=%s not found.', dn)
3500+ LOG.error(_('FakeLdap delete item failed: dn=%s not found.'), dn)
3501 raise ldap.NO_SUCH_OBJECT
3502 self.db.sync()
3503
3504@@ -237,11 +238,11 @@
3505 raise ldap.SERVER_DOWN
3506
3507 key = '%s%s' % (self.__prefix, dn)
3508- LOG.debug('FakeLdap modify item: dn=%s attrs=%s', dn, attrs)
3509+ LOG.debug(_('FakeLdap modify item: dn=%s attrs=%s'), dn, attrs)
3510 try:
3511 entry = self.db[key]
3512 except KeyError:
3513- LOG.error('FakeLdap modify item failed: dn=%s not found.', dn)
3514+ LOG.error(_('FakeLdap modify item failed: dn=%s not found.'), dn)
3515 raise ldap.NO_SUCH_OBJECT
3516
3517 for cmd, k, v in attrs:
3518@@ -258,8 +259,8 @@
3519 elif cmd == ldap.MOD_DELETE:
3520 if v is None:
3521 if len(values) == 0:
3522- LOG.error('FakeLdap modify item failed: '
3523- 'item has no attribute "%s" to delete', k)
3524+ LOG.error(_('FakeLdap modify item failed: '
3525+ 'item has no attribute "%s" to delete'), k)
3526 raise ldap.NO_SUCH_ATTRIBUTE
3527 values[:] = []
3528 else:
3529@@ -269,15 +270,15 @@
3530 try:
3531 values.remove(val)
3532 except ValueError:
3533- LOG.error('FakeLdap modify item failed:'
3534+ LOG.error(_('FakeLdap modify item failed:'
3535 ' item has no attribute "%s" with'
3536- ' value "%s" to delete', k, val)
3537+ ' value "%s" to delete'), k, val)
3538 raise ldap.NO_SUCH_ATTRIBUTE
3539 else:
3540- LOG.error('FakeLdap modify item failed: unknown'
3541- ' command %s', cmd)
3542- raise NotImplementedError('modify_s action %s not implemented'
3543- % cmd)
3544+ LOG.error(_('FakeLdap modify item failed: unknown'
3545+ ' command %s'), cmd)
3546+ raise NotImplementedError(_('modify_s action %s not'
3547+ ' implemented') % cmd)
3548 self.db[key] = entry
3549 self.db.sync()
3550
3551@@ -294,13 +295,14 @@
3552 if server_fail:
3553 raise ldap.SERVER_DOWN
3554
3555- LOG.debug('FakeLdap search at dn=%s scope=%s query=%s',
3556+ LOG.debug(_('FakeLdap search at dn=%s scope=%s query=%s'),
3557 dn, SCOPE_NAMES.get(scope, scope), query)
3558 if scope == ldap.SCOPE_BASE:
3559 try:
3560 item_dict = self.db['%s%s' % (self.__prefix, dn)]
3561 except KeyError:
3562- LOG.debug('FakeLdap search fail: dn not found for SCOPE_BASE')
3563+ LOG.debug(_('FakeLdap search fail: dn not found for'
3564+ ' SCOPE_BASE'))
3565 raise ldap.NO_SUCH_OBJECT
3566 results = [(dn, item_dict)]
3567 elif scope == ldap.SCOPE_SUBTREE:
3568@@ -313,7 +315,7 @@
3569 if re.match('%s\w+=[^,]+,%s' % (self.__prefix, dn), k)]
3570 else:
3571 LOG.error('FakeLdap search fail: unknown scope %s', scope)
3572- raise NotImplementedError('Search scope %s not implemented.'
3573+ raise NotImplementedError(_('Search scope %s not implemented.')
3574 % scope)
3575
3576 objects = []
3577
3578=== modified file 'keystone/common/models.py'
3579--- keystone/common/models.py 2012-11-02 13:48:49 +0000
3580+++ keystone/common/models.py 2013-01-25 16:27:23 +0000
3581@@ -78,7 +78,7 @@
3582 """
3583
3584 required_keys = ('id', 'region', 'service_id')
3585- optional_keys = ('interalurl', 'publicurl', 'adminurl')
3586+ optional_keys = ('internalurl', 'publicurl', 'adminurl')
3587
3588
3589 class User(Model):
3590@@ -99,6 +99,23 @@
3591 optional_keys = ('password', 'description', 'email', 'enabled')
3592
3593
3594+class Group(Model):
3595+ """Group object.
3596+
3597+ Required keys:
3598+ id
3599+ name
3600+
3601+ Optional keys:
3602+ domain_id
3603+ description
3604+
3605+ """
3606+
3607+ required_keys = ('id', 'name')
3608+ optional_keys = ('domain_id', 'description')
3609+
3610+
3611 class Tenant(Model):
3612 """Tenant object.
3613
3614
3615=== added file 'keystone/common/router.py'
3616--- keystone/common/router.py 1970-01-01 00:00:00 +0000
3617+++ keystone/common/router.py 2013-01-25 16:27:23 +0000
3618@@ -0,0 +1,56 @@
3619+# vim: tabstop=4 shiftwidth=4 softtabstop=4
3620+
3621+# Copyright 2012 OpenStack LLC
3622+#
3623+# Licensed under the Apache License, Version 2.0 (the "License"); you may
3624+# not use this file except in compliance with the License. You may obtain
3625+# a copy of the License at
3626+#
3627+# http://www.apache.org/licenses/LICENSE-2.0
3628+#
3629+# Unless required by applicable law or agreed to in writing, software
3630+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
3631+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
3632+# License for the specific language governing permissions and limitations
3633+# under the License.
3634+from keystone.common import wsgi
3635+
3636+
3637+class Router(wsgi.ComposableRouter):
3638+ def __init__(self, controller, collection_key, key):
3639+ self.controller = controller
3640+ self.key = key
3641+ self.collection_key = collection_key
3642+
3643+ def add_routes(self, mapper):
3644+ collection_path = '/%(collection_key)s' % {
3645+ 'collection_key': self.collection_key}
3646+ entity_path = '/%(collection_key)s/{%(key)s_id}' % {
3647+ 'collection_key': self.collection_key,
3648+ 'key': self.key}
3649+
3650+ mapper.connect(
3651+ collection_path,
3652+ controller=self.controller,
3653+ action='create_%s' % self.key,
3654+ conditions=dict(method=['POST']))
3655+ mapper.connect(
3656+ collection_path,
3657+ controller=self.controller,
3658+ action='list_%s' % self.collection_key,
3659+ conditions=dict(method=['GET']))
3660+ mapper.connect(
3661+ entity_path,
3662+ controller=self.controller,
3663+ action='get_%s' % self.key,
3664+ conditions=dict(method=['GET']))
3665+ mapper.connect(
3666+ entity_path,
3667+ controller=self.controller,
3668+ action='update_%s' % self.key,
3669+ conditions=dict(method=['PATCH']))
3670+ mapper.connect(
3671+ entity_path,
3672+ controller=self.controller,
3673+ action='delete_%s' % self.key,
3674+ conditions=dict(method=['DELETE']))
3675
3676=== modified file 'keystone/common/sql/core.py'
3677--- keystone/common/sql/core.py 2012-11-23 09:01:53 +0000
3678+++ keystone/common/sql/core.py 2013-01-25 16:27:23 +0000
3679@@ -46,6 +46,7 @@
3680 IntegrityError = sql.exc.IntegrityError
3681 NotFound = sql.orm.exc.NoResultFound
3682 Boolean = sql.Boolean
3683+Text = sql.Text
3684
3685
3686 def set_global_engine(engine):
3687@@ -159,7 +160,7 @@
3688 dbapi_con.cursor().execute('select 1')
3689 except dbapi_con.OperationalError as e:
3690 if e.args[0] in (2006, 2013, 2014, 2045, 2055):
3691- logging.warn('Got mysql server has gone away: %s', e)
3692+ logging.warn(_('Got mysql server has gone away: %s'), e)
3693 raise DisconnectionError("Database server went away")
3694 else:
3695 raise
3696
3697=== modified file 'keystone/common/sql/legacy.py'
3698--- keystone/common/sql/legacy.py 2012-08-16 13:59:29 +0000
3699+++ keystone/common/sql/legacy.py 2013-01-25 16:27:23 +0000
3700@@ -171,4 +171,4 @@
3701 try:
3702 self.ec2_driver.create_credential(None, new_dict)
3703 except exc.IntegrityError:
3704- LOG.exception('Cannot migrate EC2 credential: %s' % x)
3705+ LOG.exception(_('Cannot migrate EC2 credential: %s') % x)
3706
3707=== modified file 'keystone/common/sql/migrate_repo/versions/001_add_initial_tables.py'
3708--- keystone/common/sql/migrate_repo/versions/001_add_initial_tables.py 2012-11-23 09:01:53 +0000
3709+++ keystone/common/sql/migrate_repo/versions/001_add_initial_tables.py 2013-01-25 16:27:23 +0000
3710@@ -14,7 +14,6 @@
3711 # License for the specific language governing permissions and limitations
3712 # under the License.
3713
3714-import migrate
3715 import sqlalchemy as sql
3716
3717
3718@@ -116,4 +115,11 @@
3719
3720 def downgrade(migrate_engine):
3721 # Operations to reverse the above upgrade go here.
3722- pass
3723+ meta = sql.MetaData()
3724+ meta.bind = migrate_engine
3725+
3726+ tables = ['user_tenant_membership', 'token', 'user', 'tenant', 'role',
3727+ 'metadata', 'ec2_credential', 'endpoint', 'service']
3728+ for t in tables:
3729+ table = sql.Table(t, meta, autoload=True)
3730+ table.drop(migrate_engine, checkfirst=True)
3731
3732=== removed file 'keystone/common/sql/migrate_repo/versions/003_sqlite_downgrade.sql'
3733--- keystone/common/sql/migrate_repo/versions/003_sqlite_downgrade.sql 2012-09-07 13:04:01 +0000
3734+++ keystone/common/sql/migrate_repo/versions/003_sqlite_downgrade.sql 1970-01-01 00:00:00 +0000
3735@@ -1,1 +0,0 @@
3736-alter TABLE token drop column valid;
3737
3738=== modified file 'keystone/common/sql/migrate_repo/versions/003_token_valid.py'
3739--- keystone/common/sql/migrate_repo/versions/003_token_valid.py 2012-09-07 13:04:01 +0000
3740+++ keystone/common/sql/migrate_repo/versions/003_token_valid.py 2013-01-25 16:27:23 +0000
3741@@ -15,13 +15,9 @@
3742 # under the License.
3743
3744
3745-from migrate import *
3746 from sqlalchemy import *
3747
3748
3749-from keystone.common import sql
3750-
3751-
3752 def upgrade(migrate_engine):
3753 # Upgrade operations go here. Don't create your own engine; bind
3754
3755
3756=== modified file 'keystone/common/sql/migrate_repo/versions/006_add_policy_table.py'
3757--- keystone/common/sql/migrate_repo/versions/006_add_policy_table.py 2012-11-23 09:01:53 +0000
3758+++ keystone/common/sql/migrate_repo/versions/006_add_policy_table.py 2013-01-25 16:27:23 +0000
3759@@ -14,7 +14,6 @@
3760 # License for the specific language governing permissions and limitations
3761 # under the License.
3762
3763-import migrate
3764 import sqlalchemy as sql
3765
3766
3767@@ -33,4 +32,8 @@
3768
3769
3770 def downgrade(migrate_engine):
3771- pass
3772+ meta = sql.MetaData()
3773+ meta.bind = migrate_engine
3774+
3775+ policy_table = sql.Table('policy', meta, autoload=True)
3776+ policy_table.drop(migrate_engine, checkfirst=True)
3777
3778=== modified file 'keystone/common/sql/migrate_repo/versions/007_add_domain_tables.py'
3779--- keystone/common/sql/migrate_repo/versions/007_add_domain_tables.py 2012-11-23 09:01:53 +0000
3780+++ keystone/common/sql/migrate_repo/versions/007_add_domain_tables.py 2013-01-25 16:27:23 +0000
3781@@ -14,7 +14,6 @@
3782 # License for the specific language governing permissions and limitations
3783 # under the License.
3784
3785-import migrate
3786 import sqlalchemy as sql
3787
3788
3789@@ -77,3 +76,8 @@
3790
3791 role = sql.Table('role', meta, autoload=True)
3792 role.drop_column('extra')
3793+
3794+ tables = ['domain', 'user_domain_metadata', 'credential']
3795+ for t in tables:
3796+ table = sql.Table(t, meta, autoload=True)
3797+ table.drop(migrate_engine, checkfirst=True)
3798
3799=== added file 'keystone/common/sql/migrate_repo/versions/008_normalize_identity.py'
3800--- keystone/common/sql/migrate_repo/versions/008_normalize_identity.py 1970-01-01 00:00:00 +0000
3801+++ keystone/common/sql/migrate_repo/versions/008_normalize_identity.py 2013-01-25 16:27:23 +0000
3802@@ -0,0 +1,58 @@
3803+# vim: tabstop=4 shiftwidth=4 softtabstop=4
3804+
3805+# Copyright 2012 OpenStack LLC
3806+#
3807+# Licensed under the Apache License, Version 2.0 (the "License"); you may
3808+# not use this file except in compliance with the License. You may obtain
3809+# a copy of the License at
3810+#
3811+# http://www.apache.org/licenses/LICENSE-2.0
3812+#
3813+# Unless required by applicable law or agreed to in writing, software
3814+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
3815+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
3816+# License for the specific language governing permissions and limitations
3817+# under the License.
3818+
3819+
3820+from sqlalchemy import Column, MetaData, String, Table, Text, types
3821+
3822+
3823+#this won't work on sqlite. It doesn't support dropping columns
3824+def downgrade_user_table(meta, migrate_engine):
3825+ user_table = Table('user', meta, autoload=True)
3826+ user_table.columns["password"].drop()
3827+ user_table.columns["enabled"].drop()
3828+
3829+
3830+def downgrade_tenant_table(meta, migrate_engine):
3831+ tenant_table = Table('tenant', meta, autoload=True)
3832+ tenant_table.columns["description"].drop()
3833+ tenant_table.columns["enabled"].drop()
3834+
3835+
3836+def upgrade_user_table(meta, migrate_engine):
3837+ user_table = Table('user', meta, autoload=True)
3838+ user_table.create_column(Column("password", String(128)))
3839+ user_table.create_column(Column("enabled", types.Boolean,
3840+ default=True))
3841+
3842+
3843+def upgrade_tenant_table(meta, migrate_engine):
3844+ tenant_table = Table('tenant', meta, autoload=True)
3845+ tenant_table.create_column(Column("description", Text()))
3846+ tenant_table.create_column(Column("enabled", types.Boolean))
3847+
3848+
3849+def upgrade(migrate_engine):
3850+ meta = MetaData()
3851+ meta.bind = migrate_engine
3852+ upgrade_user_table(meta, migrate_engine)
3853+ upgrade_tenant_table(meta, migrate_engine)
3854+
3855+
3856+def downgrade(migrate_engine):
3857+ meta = MetaData()
3858+ meta.bind = migrate_engine
3859+ downgrade_user_table(meta, migrate_engine)
3860+ downgrade_tenant_table(meta, migrate_engine)
3861
3862=== added file 'keystone/common/sql/migrate_repo/versions/008_sqlite_downgrade.sql'
3863--- keystone/common/sql/migrate_repo/versions/008_sqlite_downgrade.sql 1970-01-01 00:00:00 +0000
3864+++ keystone/common/sql/migrate_repo/versions/008_sqlite_downgrade.sql 2013-01-25 16:27:23 +0000
3865@@ -0,0 +1,5 @@
3866+-- not supported by sqlite, but should be:
3867+-- alter TABLE tenant drop column description;
3868+-- alter TABLE tenant drop column enabled;
3869+-- The downgrade process will fail without valid SQL in this file
3870+select count(*) from tenant;
3871
3872=== added file 'keystone/common/sql/migrate_repo/versions/009_normalize_identity_migration.py'
3873--- keystone/common/sql/migrate_repo/versions/009_normalize_identity_migration.py 1970-01-01 00:00:00 +0000
3874+++ keystone/common/sql/migrate_repo/versions/009_normalize_identity_migration.py 2013-01-25 16:27:23 +0000
3875@@ -0,0 +1,145 @@
3876+# vim: tabstop=4 shiftwidth=4 softtabstop=4
3877+
3878+# Copyright 2012 OpenStack LLC
3879+#
3880+# Licensed under the Apache License, Version 2.0 (the "License"); you may
3881+# not use this file except in compliance with the License. You may obtain
3882+# a copy of the License at
3883+#
3884+# http://www.apache.org/licenses/LICENSE-2.0
3885+#
3886+# Unless required by applicable law or agreed to in writing, software
3887+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
3888+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
3889+# License for the specific language governing permissions and limitations
3890+# under the License.
3891+
3892+import json
3893+
3894+from sqlalchemy import MetaData, Table
3895+from sqlalchemy.orm import sessionmaker
3896+
3897+disabled_values = ['false', 'disabled', 'no', '0']
3898+
3899+
3900+def is_enabled(enabled):
3901+ #no explicit value means enabled
3902+ if enabled is None:
3903+ return 1
3904+ if enabled is str:
3905+ if str(enabled).lower() in disabled_values:
3906+ return 0
3907+ if enabled:
3908+ return 1
3909+ else:
3910+ return 0
3911+
3912+
3913+def downgrade_user_table(meta, migrate_engine):
3914+ user_table = Table('user', meta, autoload=True)
3915+ maker = sessionmaker(bind=migrate_engine)
3916+ session = maker()
3917+ user_data = []
3918+ for a_user in session.query(user_table):
3919+ id, name, extra, password, enabled = a_user
3920+ extra_parsed = json.loads(extra)
3921+ extra_parsed['password'] = password
3922+ extra_parsed['enabled'] = "%r" % enabled
3923+ user_data.append((password,
3924+ json.dumps(extra_parsed),
3925+ is_enabled(enabled), id))
3926+ for user in user_data:
3927+ session.execute("update user "
3928+ "set extra = '%s' "
3929+ "where id = '%s'" %
3930+ user)
3931+
3932+ session.commit()
3933+
3934+
3935+def downgrade_tenant_table(meta, migrate_engine):
3936+ tenant_table = Table('tenant', meta, autoload=True)
3937+ maker = sessionmaker(bind=migrate_engine)
3938+ session = maker()
3939+ tenant_data = []
3940+ for a_tenant in session.query(tenant_table):
3941+ id, name, extra, password, enabled = a_tenant
3942+ extra_parsed = json.loads(extra)
3943+ extra_parsed['description'] = description
3944+ extra_parsed['enabled'] = "%r" % enabled
3945+ tenant_data.append((password,
3946+ json.dumps(extra_parsed),
3947+ is_enabled(enabled), id))
3948+ for tenant in tenant_data:
3949+ session.execute("update tenant "
3950+ "set extra = '%s' "
3951+ "where id = '%s'" %
3952+ tenant)
3953+
3954+ session.commit()
3955+
3956+
3957+def upgrade_user_table(meta, migrate_engine):
3958+ user_table = Table('user', meta, autoload=True)
3959+ maker = sessionmaker(bind=migrate_engine)
3960+ session = maker()
3961+
3962+ new_user_data = []
3963+ for a_user in session.query(user_table):
3964+ id, name, extra, password, enabled = a_user
3965+ extra_parsed = json.loads(extra)
3966+ if 'password' in extra_parsed:
3967+ password = extra_parsed['password']
3968+ extra_parsed.pop('password')
3969+ if 'enabled' in extra_parsed:
3970+ enabled = extra_parsed['enabled']
3971+ extra_parsed.pop('enabled')
3972+ new_user_data.append((password,
3973+ json.dumps(extra_parsed),
3974+ is_enabled(enabled), id))
3975+ for new_user in new_user_data:
3976+ session.execute("update user "
3977+ "set password = '%s', extra = '%s', enabled = '%s' "
3978+ "where id = '%s'" %
3979+ new_user)
3980+ session.commit()
3981+
3982+
3983+def upgrade_tenant_table(meta, migrate_engine):
3984+ tenant_table = Table('tenant', meta, autoload=True)
3985+
3986+ maker = sessionmaker(bind=migrate_engine)
3987+ session = maker()
3988+ new_tenant_data = []
3989+ for a_tenant in session.query(tenant_table):
3990+ id, name, extra, description, enabled = a_tenant
3991+ extra_parsed = json.loads(extra)
3992+ if 'description' in extra_parsed:
3993+ description = extra_parsed['description']
3994+ extra_parsed.pop('description')
3995+ if 'enabled' in extra_parsed:
3996+ enabled = extra_parsed['enabled']
3997+ extra_parsed.pop('enabled')
3998+ new_tenant_data.append((description,
3999+ json.dumps(extra_parsed),
4000+ is_enabled(enabled), id))
4001+ for new_tenant in new_tenant_data:
4002+ session.execute("update tenant "
4003+ "set description = '%s', extra = '%s', enabled = '%s' "
4004+ "where id = '%s'" %
4005+ new_tenant)
4006+ session.commit()
4007+
4008+
4009+def upgrade(migrate_engine):
4010+ meta = MetaData()
4011+ meta.bind = migrate_engine
4012+ upgrade_user_table(meta, migrate_engine)
4013+ upgrade_tenant_table(meta, migrate_engine)
4014+
4015+
4016+def downgrade(migrate_engine):
4017+ meta = MetaData()
4018+ meta.bind = migrate_engine
4019+ downgrade_user_table(meta, migrate_engine)
4020+ downgrade_tenant_table(meta, migrate_engine)
4021
4022=== added file 'keystone/common/sql/migrate_repo/versions/010_endpoints_v3.py'
4023--- keystone/common/sql/migrate_repo/versions/010_endpoints_v3.py 1970-01-01 00:00:00 +0000
4024+++ keystone/common/sql/migrate_repo/versions/010_endpoints_v3.py 2013-01-25 16:27:23 +0000
4025@@ -0,0 +1,53 @@
4026+# vim: tabstop=4 shiftwidth=4 softtabstop=4
4027+
4028+# Copyright 2012 OpenStack LLC
4029+#
4030+# Licensed under the Apache License, Version 2.0 (the "License"); you may
4031+# not use this file except in compliance with the License. You may obtain
4032+# a copy of the License at
4033+#
4034+# http://www.apache.org/licenses/LICENSE-2.0
4035+#
4036+# Unless required by applicable law or agreed to in writing, software
4037+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
4038+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
4039+# License for the specific language governing permissions and limitations
4040+# under the License.
4041+
4042+import sqlalchemy as sql
4043+
4044+
4045+def upgrade(migrate_engine):
4046+ """Create API-version specific endpoint tables."""
4047+ meta = sql.MetaData()
4048+ meta.bind = migrate_engine
4049+
4050+ legacy_table = sql.Table('endpoint', meta, autoload=True)
4051+ legacy_table.rename('endpoint_v2')
4052+
4053+ new_table = sql.Table(
4054+ 'endpoint_v3',
4055+ meta,
4056+ sql.Column('id', sql.String(64), primary_key=True),
4057+ sql.Column('legacy_endpoint_id', sql.String(64)),
4058+ sql.Column('interface', sql.String(8), nullable=False),
4059+ sql.Column('region', sql.String(255)),
4060+ sql.Column('service_id',
4061+ sql.String(64),
4062+ sql.ForeignKey('service.id'),
4063+ nullable=False),
4064+ sql.Column('url', sql.Text(), nullable=False),
4065+ sql.Column('extra', sql.Text()))
4066+ new_table.create(migrate_engine, checkfirst=True)
4067+
4068+
4069+def downgrade(migrate_engine):
4070+ """Replace API-version specific endpoint tables with one based on v2."""
4071+ meta = sql.MetaData()
4072+ meta.bind = migrate_engine
4073+
4074+ new_table = sql.Table('endpoint_v3', meta, autoload=True)
4075+ new_table.drop()
4076+
4077+ legacy_table = sql.Table('endpoint_v2', meta, autoload=True)
4078+ legacy_table.rename('endpoint')
4079
4080=== added file 'keystone/common/sql/migrate_repo/versions/011_populate_endpoint_type.py'
4081--- keystone/common/sql/migrate_repo/versions/011_populate_endpoint_type.py 1970-01-01 00:00:00 +0000
4082+++ keystone/common/sql/migrate_repo/versions/011_populate_endpoint_type.py 2013-01-25 16:27:23 +0000
4083@@ -0,0 +1,96 @@
4084+# vim: tabstop=4 shiftwidth=4 softtabstop=4
4085+
4086+# Copyright 2012 OpenStack LLC
4087+#
4088+# Licensed under the Apache License, Version 2.0 (the "License"); you may
4089+# not use this file except in compliance with the License. You may obtain
4090+# a copy of the License at
4091+#
4092+# http://www.apache.org/licenses/LICENSE-2.0
4093+#
4094+# Unless required by applicable law or agreed to in writing, software
4095+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
4096+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
4097+# License for the specific language governing permissions and limitations
4098+# under the License.
4099+
4100+import json
4101+import uuid
4102+
4103+import sqlalchemy as sql
4104+from sqlalchemy import orm
4105+
4106+
4107+ENDPOINT_TYPES = ['public', 'internal', 'admin']
4108+
4109+
4110+def upgrade(migrate_engine):
4111+ """Split each legacy endpoint into seperate records for each interface."""
4112+ meta = sql.MetaData()
4113+ meta.bind = migrate_engine
4114+
4115+ legacy_table = sql.Table('endpoint_v2', meta, autoload=True)
4116+ new_table = sql.Table('endpoint_v3', meta, autoload=True)
4117+
4118+ session = orm.sessionmaker(bind=migrate_engine)()
4119+ for ref in session.query(legacy_table).all():
4120+ # pull urls out of extra
4121+ extra = json.loads(ref.extra)
4122+ urls = dict((i, extra.pop('%surl' % i)) for i in ENDPOINT_TYPES)
4123+
4124+ for interface in ENDPOINT_TYPES:
4125+ endpoint = {
4126+ 'id': uuid.uuid4().hex,
4127+ 'legacy_endpoint_id': ref.id,
4128+ 'interface': interface,
4129+ 'region': ref.region,
4130+ 'service_id': ref.service_id,
4131+ 'url': urls[interface],
4132+ 'extra': json.dumps(extra),
4133+ }
4134+ session.execute(
4135+ 'INSERT INTO `%s` (%s) VALUES (%s)' % (
4136+ new_table.name,
4137+ ', '.join('%s' % k for k in endpoint.keys()),
4138+ ', '.join("'%s'" % v for v in endpoint.values())))
4139+ session.commit()
4140+
4141+
4142+def downgrade(migrate_engine):
4143+ """Re-create the v2 endpoints table based on v3 endpoints."""
4144+ meta = sql.MetaData()
4145+ meta.bind = migrate_engine
4146+
4147+ legacy_table = sql.Table('endpoint_v2', meta, autoload=True)
4148+ new_table = sql.Table('endpoint_v3', meta, autoload=True)
4149+
4150+ session = orm.sessionmaker(bind=migrate_engine)()
4151+ for ref in session.query(new_table).all():
4152+ extra = json.loads(ref.extra)
4153+ extra['%surl' % ref.interface] = ref.url
4154+ endpoint = {
4155+ 'id': ref.legacy_endpoint_id,
4156+ 'region': ref.region,
4157+ 'service_id': ref.service_id,
4158+ 'extra': json.dumps(extra),
4159+ }
4160+
4161+ try:
4162+ session.execute(
4163+ 'INSERT INTO `%s` (%s) VALUES (%s)' % (
4164+ legacy_table.name,
4165+ ', '.join('%s' % k for k in endpoint.keys()),
4166+ ', '.join("'%s'" % v for v in endpoint.values())))
4167+ except sql.exc.IntegrityError:
4168+ q = session.query(legacy_table)
4169+ q = q.filter_by(id=ref.legacy_endpoint_id)
4170+ legacy_ref = q.one()
4171+ extra = json.loads(legacy_ref.extra)
4172+ extra['%surl' % ref.interface] = ref.url
4173+
4174+ session.execute(
4175+ 'UPDATE `%s` SET extra=\'%s\' WHERE id="%s"' % (
4176+ legacy_table.name,
4177+ json.dumps(extra),
4178+ legacy_ref.id))
4179+ session.commit()
4180
4181=== added file 'keystone/common/sql/migrate_repo/versions/012_drop_legacy_endpoints.py'
4182--- keystone/common/sql/migrate_repo/versions/012_drop_legacy_endpoints.py 1970-01-01 00:00:00 +0000
4183+++ keystone/common/sql/migrate_repo/versions/012_drop_legacy_endpoints.py 2013-01-25 16:27:23 +0000
4184@@ -0,0 +1,50 @@
4185+# vim: tabstop=4 shiftwidth=4 softtabstop=4
4186+
4187+# Copyright 2012 OpenStack LLC
4188+#
4189+# Licensed under the Apache License, Version 2.0 (the "License"); you may
4190+# not use this file except in compliance with the License. You may obtain
4191+# a copy of the License at
4192+#
4193+# http://www.apache.org/licenses/LICENSE-2.0
4194+#
4195+# Unless required by applicable law or agreed to in writing, software
4196+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
4197+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
4198+# License for the specific language governing permissions and limitations
4199+# under the License.
4200+
4201+import sqlalchemy as sql
4202+
4203+
4204+def upgrade(migrate_engine):
4205+ """Replace API-version specific endpoint tables with one based on v3."""
4206+ meta = sql.MetaData()
4207+ meta.bind = migrate_engine
4208+
4209+ legacy_table = sql.Table('endpoint_v2', meta, autoload=True)
4210+ legacy_table.drop()
4211+
4212+ new_table = sql.Table('endpoint_v3', meta, autoload=True)
4213+ new_table.rename('endpoint')
4214+
4215+
4216+def downgrade(migrate_engine):
4217+ """Create API-version specific endpoint tables."""
4218+ meta = sql.MetaData()
4219+ meta.bind = migrate_engine
4220+
4221+ new_table = sql.Table('endpoint', meta, autoload=True)
4222+ new_table.rename('endpoint_v3')
4223+
4224+ legacy_table = sql.Table(
4225+ 'endpoint_v2',
4226+ meta,
4227+ sql.Column('id', sql.String(64), primary_key=True),
4228+ sql.Column('region', sql.String(255)),
4229+ sql.Column('service_id',
4230+ sql.String(64),
4231+ sql.ForeignKey('service.id'),
4232+ nullable=False),
4233+ sql.Column('extra', sql.Text()))
4234+ legacy_table.create(migrate_engine, checkfirst=True)
4235
4236=== added file 'keystone/common/sql/migrate_repo/versions/013_add_group_tables.py'
4237--- keystone/common/sql/migrate_repo/versions/013_add_group_tables.py 1970-01-01 00:00:00 +0000
4238+++ keystone/common/sql/migrate_repo/versions/013_add_group_tables.py 2013-01-25 16:27:23 +0000
4239@@ -0,0 +1,93 @@
4240+# vim: tabstop=4 shiftwidth=4 softtabstop=4
4241+
4242+# Copyright 2012 OpenStack LLC
4243+#
4244+# Licensed under the Apache License, Version 2.0 (the "License"); you may
4245+# not use this file except in compliance with the License. You may obtain
4246+# a copy of the License at
4247+#
4248+# http://www.apache.org/licenses/LICENSE-2.0
4249+#
4250+# Unless required by applicable law or agreed to in writing, software
4251+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
4252+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
4253+# License for the specific language governing permissions and limitations
4254+# under the License.
4255+
4256+import sqlalchemy as sql
4257+
4258+
4259+def upgrade(migrate_engine):
4260+ meta = sql.MetaData()
4261+ meta.bind = migrate_engine
4262+
4263+ sql.Table('domain', meta, autoload=True)
4264+ group_table = sql.Table(
4265+ 'group',
4266+ meta,
4267+ sql.Column('id', sql.String(64), primary_key=True),
4268+ sql.Column('domain_id', sql.String(64), sql.ForeignKey('domain.id')),
4269+ sql.Column('name', sql.String(64), unique=True, nullable=False),
4270+ sql.Column('description', sql.Text()),
4271+ sql.Column('extra', sql.Text()))
4272+ group_table.create(migrate_engine, checkfirst=True)
4273+
4274+ sql.Table('user', meta, autoload=True)
4275+ user_group_membership_table = sql.Table(
4276+ 'user_group_membership',
4277+ meta,
4278+ sql.Column(
4279+ 'user_id',
4280+ sql.String(64),
4281+ sql.ForeignKey('user.id'),
4282+ primary_key=True),
4283+ sql.Column(
4284+ 'group_id',
4285+ sql.String(64),
4286+ sql.ForeignKey('group.id'),
4287+ primary_key=True))
4288+ user_group_membership_table.create(migrate_engine, checkfirst=True)
4289+
4290+ sql.Table('tenant', meta, autoload=True)
4291+ group_project_metadata_table = sql.Table(
4292+ 'group_project_metadata',
4293+ meta,
4294+ sql.Column(
4295+ 'group_id',
4296+ sql.String(64),
4297+ sql.ForeignKey('group.id'),
4298+ primary_key=True),
4299+ sql.Column(
4300+ 'project_id',
4301+ sql.String(64),
4302+ sql.ForeignKey('tenant.id'),
4303+ primary_key=True),
4304+ sql.Column('data', sql.Text()))
4305+ group_project_metadata_table.create(migrate_engine, checkfirst=True)
4306+
4307+ group_domain_metadata_table = sql.Table(
4308+ 'group_domain_metadata',
4309+ meta,
4310+ sql.Column(
4311+ 'group_id',
4312+ sql.String(64),
4313+ sql.ForeignKey('group.id'),
4314+ primary_key=True),
4315+ sql.Column(
4316+ 'domain_id',
4317+ sql.String(64),
4318+ sql.ForeignKey('domain.id'),
4319+ primary_key=True),
4320+ sql.Column('data', sql.Text()))
4321+ group_domain_metadata_table.create(migrate_engine, checkfirst=True)
4322+
4323+
4324+def downgrade(migrate_engine):
4325+ meta = sql.MetaData()
4326+ meta.bind = migrate_engine
4327+
4328+ tables = ['user_group_membership', 'group_project_metadata',
4329+ 'group_domain_metadata', 'group']
4330+ for t in tables:
4331+ table = sql.Table(t, meta, autoload=True)
4332+ table.drop(migrate_engine, checkfirst=True)
4333
4334=== modified file 'keystone/common/sql/migration.py'
4335--- keystone/common/sql/migration.py 2012-06-22 12:27:50 +0000
4336+++ keystone/common/sql/migration.py 2013-01-25 16:27:23 +0000
4337@@ -44,7 +44,7 @@
4338 try:
4339 version = int(version)
4340 except ValueError:
4341- raise Exception('version should be an integer')
4342+ raise Exception(_('version should be an integer'))
4343
4344 current_version = db_version()
4345 repo_path = _find_migrate_repo()
4346
4347=== modified file 'keystone/common/sql/nova.py'
4348--- keystone/common/sql/nova.py 2012-06-22 12:27:50 +0000
4349+++ keystone/common/sql/nova.py 2013-01-25 16:27:23 +0000
4350@@ -55,7 +55,7 @@
4351 'enabled': True,
4352 }
4353 tenant_map[tenant['id']] = tenant_dict['id']
4354- LOG.debug('Create tenant %s' % tenant_dict)
4355+ LOG.debug(_('Create tenant %s') % tenant_dict)
4356 api.create_tenant(tenant_dict['id'], tenant_dict)
4357 return tenant_map
4358
4359@@ -71,7 +71,7 @@
4360 'enabled': True,
4361 }
4362 user_map[user['id']] = user_dict['id']
4363- LOG.debug('Create user %s' % user_dict)
4364+ LOG.debug(_('Create user %s') % user_dict)
4365 api.create_user(user_dict['id'], user_dict)
4366 return user_map
4367
4368@@ -80,7 +80,7 @@
4369 for membership in memberships:
4370 user_id = user_map[membership['user_id']]
4371 tenant_id = tenant_map[membership['tenant_id']]
4372- LOG.debug('Add user %s to tenant %s' % (user_id, tenant_id))
4373+ LOG.debug(_('Add user %s to tenant %s') % (user_id, tenant_id))
4374 api.add_user_to_tenant(tenant_id, user_id)
4375
4376
4377@@ -88,14 +88,14 @@
4378 role_map = dict((r['name'], r['id']) for r in api.list_roles())
4379 for role in roles:
4380 if role in role_map:
4381- LOG.debug('Ignoring existing role %s' % role)
4382+ LOG.debug(_('Ignoring existing role %s') % role)
4383 continue
4384 role_dict = {
4385 'id': _generate_uuid(),
4386 'name': role,
4387 }
4388 role_map[role] = role_dict['id']
4389- LOG.debug('Create role %s' % role_dict)
4390+ LOG.debug(_('Create role %s') % role_dict)
4391 api.create_role(role_dict['id'], role_dict)
4392 return role_map
4393
4394@@ -105,7 +105,7 @@
4395 role_id = role_map[assignment['role']]
4396 user_id = user_map[assignment['user_id']]
4397 tenant_id = tenant_map[assignment['tenant_id']]
4398- LOG.debug('Assign role %s to user %s on tenant %s' %
4399+ LOG.debug(_('Assign role %s to user %s on tenant %s') %
4400 (role_id, user_id, tenant_id))
4401 api.add_role_to_user_and_tenant(user_id, tenant_id, role_id)
4402
4403@@ -120,6 +120,6 @@
4404 'user_id': user_id,
4405 'tenant_id': tenant_id,
4406 }
4407- LOG.debug('Creating ec2 cred for user %s and tenant %s' %
4408+ LOG.debug(_('Creating ec2 cred for user %s and tenant %s') %
4409 (user_id, tenant_id))
4410 ec2_api.create_credential(None, cred_dict)
4411
4412=== modified file 'keystone/common/utils.py'
4413--- keystone/common/utils.py 2012-11-02 13:48:49 +0000
4414+++ keystone/common/utils.py 2013-01-25 16:27:23 +0000
4415@@ -31,6 +31,7 @@
4416
4417 from keystone.common import logging
4418 from keystone import config
4419+from keystone import exception
4420
4421
4422 CONF = config.CONF
4423@@ -89,8 +90,8 @@
4424 credentials['verb'],
4425 credentials['host'],
4426 credentials['path'])
4427- raise Exception('Unknown Signature Version: %s' %
4428- credentials['params']['SignatureVersion'])
4429+ raise Exception(_('Unknown Signature Version: %s' %
4430+ credentials['params']['SignatureVersion']))
4431
4432 @staticmethod
4433 def _get_utf8_value(value):
4434@@ -120,7 +121,7 @@
4435
4436 def _calc_signature_2(self, params, verb, server_string, path):
4437 """Generate AWS signature version 2 string."""
4438- LOG.debug('using _calc_signature_2')
4439+ LOG.debug(_('using _calc_signature_2'))
4440 string_to_sign = '%s\n%s\n%s\n' % (verb, server_string, path)
4441 if self.hmac_256:
4442 current_hmac = self.hmac_256
4443@@ -136,22 +137,25 @@
4444 val = urllib.quote(val, safe='-_~')
4445 pairs.append(urllib.quote(key, safe='') + '=' + val)
4446 qs = '&'.join(pairs)
4447- LOG.debug('query string: %s', qs)
4448+ LOG.debug(_('query string: %s'), qs)
4449 string_to_sign += qs
4450- LOG.debug('string_to_sign: %s', string_to_sign)
4451+ LOG.debug(_('string_to_sign: %s'), string_to_sign)
4452 current_hmac.update(string_to_sign)
4453 b64 = base64.b64encode(current_hmac.digest())
4454- LOG.debug('len(b64)=%d', len(b64))
4455- LOG.debug('base64 encoded digest: %s', b64)
4456+ LOG.debug(_('len(b64)=%d'), len(b64))
4457+ LOG.debug(_('base64 encoded digest: %s'), b64)
4458 return b64
4459
4460
4461 def trunc_password(password):
4462 """Truncate passwords to the MAX_PASSWORD_LENGTH."""
4463- if len(password) > MAX_PASSWORD_LENGTH:
4464- return password[:MAX_PASSWORD_LENGTH]
4465- else:
4466- return password
4467+ try:
4468+ if len(password) > MAX_PASSWORD_LENGTH:
4469+ return password[:MAX_PASSWORD_LENGTH]
4470+ else:
4471+ return password
4472+ except TypeError:
4473+ raise exception.ValidationError(attribute='string', target='password')
4474
4475
4476 def hash_user_password(user):
4477@@ -288,3 +292,22 @@
4478 hash_ = hashlib.md5()
4479 hash_.update(signed_text)
4480 return hash_.hexdigest()
4481+
4482+
4483+def setup_remote_pydev_debug():
4484+ if CONF.pydev_debug_host and CONF.pydev_debug_port:
4485+ error_msg = ('Error setting up the debug environment. Verify that the'
4486+ ' option --debug-url has the format <host>:<port> and '
4487+ 'that a debugger processes is listening on that port.')
4488+
4489+ try:
4490+ from pydev import pydevd
4491+
4492+ pydevd.settrace(CONF.pydev_debug_host,
4493+ port=CONF.pydev_debug_port,
4494+ stdoutToServer=True,
4495+ stderrToServer=True)
4496+ return True
4497+ except:
4498+ LOG.exception(_(error_msg))
4499+ raise
4500
4501=== modified file 'keystone/common/wsgi.py'
4502--- keystone/common/wsgi.py 2012-11-23 09:01:53 +0000
4503+++ keystone/common/wsgi.py 2013-01-25 16:27:23 +0000
4504@@ -70,7 +70,7 @@
4505
4506 def start(self, key=None, backlog=128):
4507 """Run a WSGI server with the given application."""
4508- LOG.debug('Starting %(arg0)s on %(host)s:%(port)s' %
4509+ LOG.debug(_('Starting %(arg0)s on %(host)s:%(port)s') %
4510 {'arg0': sys.argv[0],
4511 'host': self.host,
4512 'port': self.port})
4513@@ -193,7 +193,7 @@
4514 arg_dict = req.environ['wsgiorg.routing_args'][1]
4515 action = arg_dict.pop('action')
4516 del arg_dict['controller']
4517- LOG.debug('arg_dict: %s', arg_dict)
4518+ LOG.debug(_('arg_dict: %s'), arg_dict)
4519
4520 # allow middleware up the stack to provide context & params
4521 context = req.environ.get(CONTEXT_ENV, {})
4522@@ -214,7 +214,7 @@
4523 try:
4524 result = method(context, **params)
4525 except exception.Unauthorized as e:
4526- LOG.warning("Authorization failed. %s from %s"
4527+ LOG.warning(_("Authorization failed. %s from %s")
4528 % (e, req.environ['REMOTE_ADDR']))
4529 return render_exception(e)
4530 except exception.Error as e:
4531@@ -427,7 +427,7 @@
4532 match = req.environ['wsgiorg.routing_args'][1]
4533 if not match:
4534 return render_exception(
4535- exception.NotFound(message='The resource could not be found.'))
4536+ exception.NotFound(_('The resource could not be found.')))
4537 app = match['controller']
4538 return app
4539
4540
4541=== modified file 'keystone/config.py'
4542--- keystone/config.py 2012-11-23 09:01:53 +0000
4543+++ keystone/config.py 2013-01-25 16:27:23 +0000
4544@@ -41,8 +41,8 @@
4545 logging.config.fileConfig(conf.log_config)
4546 return
4547 else:
4548- raise RuntimeError('Unable to locate specified logging '
4549- 'config file: %s' % conf.log_config)
4550+ raise RuntimeError(_('Unable to locate specified logging '
4551+ 'config file: %s') % conf.log_config)
4552
4553 root_logger = logging.root
4554 if conf.debug:
4555@@ -122,6 +122,12 @@
4556 group = kw.pop('group', None)
4557 return conf.register_cli_opt(cfg.IntOpt(*args, **kw), group=group)
4558
4559+
4560+register_cli_bool('standard-threads', default=False)
4561+
4562+register_cli_str('pydev-debug-host', default=None)
4563+register_cli_int('pydev-debug-port', default=None)
4564+
4565 register_str('admin_token', default='ADMIN')
4566 register_str('bind_host', default='0.0.0.0')
4567 register_str('compute_port', default=8774)
4568@@ -129,7 +135,6 @@
4569 register_str('public_port', default=5000)
4570 register_str('onready')
4571 register_str('auth_admin_prefix', default='')
4572-register_bool('standard-threads', default=False)
4573 register_str('policy_file', default='policy.json')
4574 register_str('policy_default_rule', default=None)
4575
4576@@ -221,6 +226,17 @@
4577 register_bool('role_allow_update', group='ldap', default=True)
4578 register_bool('role_allow_delete', group='ldap', default=True)
4579
4580+register_str('group_tree_dn', group='ldap', default=None)
4581+register_str('group_filter', group='ldap', default=None)
4582+register_str('group_objectclass', group='ldap', default='groupOfNames')
4583+register_str('group_id_attribute', group='ldap', default='cn')
4584+register_str('group_name_attribute', group='ldap', default='ou')
4585+register_str('group_member_attribute', group='ldap', default='member')
4586+register_str('group_desc_attribute', group='ldap', default='desc')
4587+register_list('group_attribute_ignore', group='ldap', default='')
4588+register_bool('group_allow_create', group='ldap', default=True)
4589+register_bool('group_allow_update', group='ldap', default=True)
4590+register_bool('group_allow_delete', group='ldap', default=True)
4591 #pam
4592 register_str('url', group='pam', default=None)
4593 register_str('userid', group='pam', default=None)
4594
4595=== modified file 'keystone/contrib/admin_crud/core.py'
4596--- keystone/contrib/admin_crud/core.py 2012-07-06 10:37:01 +0000
4597+++ keystone/contrib/admin_crud/core.py 2013-01-25 16:27:23 +0000
4598@@ -13,7 +13,6 @@
4599 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
4600 # License for the specific language governing permissions and limitations
4601 # under the License.
4602-
4603 from keystone import catalog
4604 from keystone.common import wsgi
4605 from keystone import identity
4606@@ -27,11 +26,11 @@
4607 """
4608
4609 def add_routes(self, mapper):
4610- tenant_controller = identity.TenantController()
4611- user_controller = identity.UserController()
4612- role_controller = identity.RoleController()
4613- service_controller = catalog.ServiceController()
4614- endpoint_controller = catalog.EndpointController()
4615+ tenant_controller = identity.controllers.Tenant()
4616+ user_controller = identity.controllers.User()
4617+ role_controller = identity.controllers.Role()
4618+ service_controller = catalog.controllers.Service()
4619+ endpoint_controller = catalog.controllers.Endpoint()
4620
4621 # Tenant Operations
4622 mapper.connect(
4623
4624=== modified file 'keystone/contrib/ec2/core.py'
4625--- keystone/contrib/ec2/core.py 2012-11-23 09:01:53 +0000
4626+++ keystone/contrib/ec2/core.py 2013-01-25 16:27:23 +0000
4627@@ -36,21 +36,20 @@
4628
4629 import uuid
4630
4631-from keystone import catalog
4632+from keystone.common import controller
4633+from keystone.common import dependency
4634 from keystone.common import manager
4635 from keystone.common import utils
4636 from keystone.common import wsgi
4637 from keystone import config
4638 from keystone import exception
4639-from keystone import identity
4640-from keystone import policy
4641-from keystone import service
4642 from keystone import token
4643
4644
4645 CONF = config.CONF
4646
4647
4648+@dependency.provider('ec2_api')
4649 class Manager(manager.Manager):
4650 """Default pivot point for the EC2 Credentials backend.
4651
4652@@ -96,15 +95,8 @@
4653 conditions=dict(method=['DELETE']))
4654
4655
4656-class Ec2Controller(wsgi.Application):
4657- def __init__(self):
4658- self.catalog_api = catalog.Manager()
4659- self.identity_api = identity.Manager()
4660- self.token_api = token.Manager()
4661- self.policy_api = policy.Manager()
4662- self.ec2_api = Manager()
4663- super(Ec2Controller, self).__init__()
4664-
4665+@dependency.requires('catalog_api', 'ec2_api')
4666+class Ec2Controller(controller.V2Controller):
4667 def check_signature(self, creds_ref, credentials):
4668 signer = utils.Ec2Signer(creds_ref['secret'])
4669 signature = signer.generate(credentials)
4670@@ -190,12 +182,10 @@
4671 tenant=tenant_ref,
4672 metadata=metadata_ref))
4673
4674- # TODO(termie): make this a util function or something
4675 # TODO(termie): i don't think the ec2 middleware currently expects a
4676 # full return, but it contains a note saying that it
4677 # would be better to expect a full return
4678- token_controller = service.TokenController()
4679- return token_controller._format_authenticate(
4680+ return token.controllers.Auth.format_authenticate(
4681 token_ref, roles_ref, catalog_ref)
4682
4683 def create_credential(self, context, user_id, tenant_id):
4684
4685=== modified file 'keystone/contrib/user_crud/core.py'
4686--- keystone/contrib/user_crud/core.py 2012-11-23 09:01:53 +0000
4687+++ keystone/contrib/user_crud/core.py 2013-01-25 16:27:23 +0000
4688@@ -20,20 +20,13 @@
4689 from keystone import exception
4690 from keystone.common import logging
4691 from keystone.common import wsgi
4692-from keystone.identity import Manager as IdentityManager
4693-from keystone.identity import UserController as UserManager
4694-from keystone.token import Manager as TokenManager
4695+from keystone import identity
4696
4697
4698 LOG = logging.getLogger(__name__)
4699
4700
4701-class UserController(wsgi.Application):
4702- def __init__(self):
4703- self.identity_api = IdentityManager()
4704- self.token_api = TokenManager()
4705- self.user_controller = UserManager()
4706-
4707+class UserController(identity.controllers.User):
4708 def set_user_password(self, context, user_id, user):
4709 token_id = context.get('token_id')
4710 original_password = user.get('original_password')
4711@@ -63,9 +56,9 @@
4712
4713 admin_context = copy.copy(context)
4714 admin_context['is_admin'] = True
4715- self.user_controller.set_user_password(admin_context,
4716- user_id,
4717- update_dict)
4718+ super(UserController, self).set_user_password(admin_context,
4719+ user_id,
4720+ update_dict)
4721
4722 token_id = uuid.uuid4().hex
4723 new_token_ref = copy.copy(token_ref)
4724
4725=== added file 'keystone/controllers.py'
4726--- keystone/controllers.py 1970-01-01 00:00:00 +0000
4727+++ keystone/controllers.py 2013-01-25 16:27:23 +0000
4728@@ -0,0 +1,144 @@
4729+# vim: tabstop=4 shiftwidth=4 softtabstop=4
4730+
4731+# Copyright 2012 OpenStack LLC
4732+#
4733+# Licensed under the Apache License, Version 2.0 (the "License"); you may
4734+# not use this file except in compliance with the License. You may obtain
4735+# a copy of the License at
4736+#
4737+# http://www.apache.org/licenses/LICENSE-2.0
4738+#
4739+# Unless required by applicable law or agreed to in writing, software
4740+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
4741+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
4742+# License for the specific language governing permissions and limitations
4743+# under the License.
4744+
4745+from keystone.common import wsgi
4746+from keystone import catalog
4747+from keystone import exception
4748+
4749+
4750+class Extensions(wsgi.Application):
4751+ """Base extensions controller to be extended by public and admin API's."""
4752+
4753+ def __init__(self, extensions=None):
4754+ super(Extensions, self).__init__()
4755+
4756+ self.extensions = extensions or {}
4757+
4758+ def get_extensions_info(self, context):
4759+ return {'extensions': {'values': self.extensions.values()}}
4760+
4761+ def get_extension_info(self, context, extension_alias):
4762+ try:
4763+ return {'extension': self.extensions[extension_alias]}
4764+ except KeyError:
4765+ raise exception.NotFound(target=extension_alias)
4766+
4767+
4768+class AdminExtensions(Extensions):
4769+ def __init__(self, *args, **kwargs):
4770+ super(AdminExtensions, self).__init__(*args, **kwargs)
4771+
4772+ # TODO(dolph): Extensions should obviously provide this information
4773+ # themselves, but hardcoding it here allows us to match
4774+ # the API spec in the short term with minimal complexity.
4775+ self.extensions['OS-KSADM'] = {
4776+ 'name': 'Openstack Keystone Admin',
4777+ 'namespace': 'http://docs.openstack.org/identity/api/ext/'
4778+ 'OS-KSADM/v1.0',
4779+ 'alias': 'OS-KSADM',
4780+ 'updated': '2011-08-19T13:25:27-06:00',
4781+ 'description': 'Openstack extensions to Keystone v2.0 API '
4782+ 'enabling Admin Operations.',
4783+ 'links': [
4784+ {
4785+ 'rel': 'describedby',
4786+ # TODO(dolph): link needs to be revised after
4787+ # bug 928059 merges
4788+ 'type': 'text/html',
4789+ 'href': 'https://github.com/openstack/identity-api',
4790+ }
4791+ ]
4792+ }
4793+
4794+
4795+class PublicExtensions(Extensions):
4796+ pass
4797+
4798+
4799+class Version(wsgi.Application):
4800+ def __init__(self, version_type):
4801+ self.catalog_api = catalog.Manager()
4802+ self.url_key = '%sURL' % version_type
4803+
4804+ super(Version, self).__init__()
4805+
4806+ def _get_identity_url(self, context):
4807+ catalog_ref = self.catalog_api.get_catalog(context=context,
4808+ user_id=None,
4809+ tenant_id=None)
4810+ for region, region_ref in catalog_ref.iteritems():
4811+ for service, service_ref in region_ref.iteritems():
4812+ if service == 'identity':
4813+ return service_ref[self.url_key]
4814+
4815+ raise exception.NotImplemented()
4816+
4817+ def _get_versions_list(self, context):
4818+ """The list of versions is dependent on the context."""
4819+ identity_url = self._get_identity_url(context)
4820+ if not identity_url.endswith('/'):
4821+ identity_url = identity_url + '/'
4822+
4823+ versions = {}
4824+ versions['v2.0'] = {
4825+ 'id': 'v2.0',
4826+ 'status': 'beta',
4827+ 'updated': '2011-11-19T00:00:00Z',
4828+ 'links': [
4829+ {
4830+ 'rel': 'self',
4831+ 'href': identity_url,
4832+ }, {
4833+ 'rel': 'describedby',
4834+ 'type': 'text/html',
4835+ 'href': 'http://docs.openstack.org/api/openstack-'
4836+ 'identity-service/2.0/content/'
4837+ }, {
4838+ 'rel': 'describedby',
4839+ 'type': 'application/pdf',
4840+ 'href': 'http://docs.openstack.org/api/openstack-'
4841+ 'identity-service/2.0/identity-dev-guide-'
4842+ '2.0.pdf'
4843+ }
4844+ ],
4845+ 'media-types': [
4846+ {
4847+ 'base': 'application/json',
4848+ 'type': 'application/vnd.openstack.identity-v2.0'
4849+ '+json'
4850+ }, {
4851+ 'base': 'application/xml',
4852+ 'type': 'application/vnd.openstack.identity-v2.0'
4853+ '+xml'
4854+ }
4855+ ]
4856+ }
4857+
4858+ return versions
4859+
4860+ def get_versions(self, context):
4861+ versions = self._get_versions_list(context)
4862+ return wsgi.render_response(status=(300, 'Multiple Choices'), body={
4863+ 'versions': {
4864+ 'values': versions.values()
4865+ }
4866+ })
4867+
4868+ def get_version(self, context):
4869+ versions = self._get_versions_list(context)
4870+ return wsgi.render_response(body={
4871+ 'version': versions['v2.0']
4872+ })
4873
4874=== modified file 'keystone/exception.py'
4875--- keystone/exception.py 2012-11-23 09:01:53 +0000
4876+++ keystone/exception.py 2013-01-25 16:27:23 +0000
4877@@ -148,6 +148,10 @@
4878 """Could not find user: %(user_id)s"""
4879
4880
4881+class GroupNotFound(NotFound):
4882+ """Could not find group: %(group_id)s"""
4883+
4884+
4885 class Conflict(Error):
4886 """Conflict occurred attempting to store %(type)s.
4887
4888
4889=== modified file 'keystone/identity/__init__.py'
4890--- keystone/identity/__init__.py 2012-03-16 11:19:40 +0000
4891+++ keystone/identity/__init__.py 2013-01-25 16:27:23 +0000
4892@@ -15,3 +15,5 @@
4893 # under the License.
4894
4895 from keystone.identity.core import *
4896+from keystone.identity import controllers
4897+from keystone.identity import routers
4898
4899=== modified file 'keystone/identity/backends/kvs.py'
4900--- keystone/identity/backends/kvs.py 2012-11-23 09:01:53 +0000
4901+++ keystone/identity/backends/kvs.py 2013-01-25 16:27:23 +0000
4902@@ -97,9 +97,13 @@
4903 def get_user_by_name(self, user_name):
4904 return identity.filter_user(self._get_user_by_name(user_name))
4905
4906- def get_metadata(self, user_id, tenant_id):
4907+ def get_metadata(self, user_id=None, tenant_id=None,
4908+ domain_id=None, group_id=None):
4909 try:
4910- return self.db.get('metadata-%s-%s' % (tenant_id, user_id))
4911+ if user_id:
4912+ return self.db.get('metadata-%s-%s' % (tenant_id, user_id))
4913+ else:
4914+ return self.db.get('metadata-%s-%s' % (tenant_id, group_id))
4915 except exception.NotFound:
4916 raise exception.MetadataNotFound()
4917
4918@@ -199,12 +203,16 @@
4919 raise exception.Conflict(type='user', details=msg)
4920
4921 user = utils.hash_user_password(user)
4922- self.db.set('user-%s' % user_id, user)
4923- self.db.set('user_name-%s' % user['name'], user)
4924+ new_user = user.copy()
4925+
4926+ new_user.setdefault('groups', [])
4927+
4928+ self.db.set('user-%s' % user_id, new_user)
4929+ self.db.set('user_name-%s' % new_user['name'], new_user)
4930 user_list = set(self.db.get('user_list', []))
4931 user_list.add(user_id)
4932 self.db.set('user_list', list(user_list))
4933- return identity.filter_user(user)
4934+ return identity.filter_user(new_user)
4935
4936 def update_user(self, user_id, user):
4937 if 'name' in user:
4938@@ -228,6 +236,42 @@
4939 self.db.set('user_name-%s' % new_user['name'], new_user)
4940 return new_user
4941
4942+ def add_user_to_group(self, user_id, group_id):
4943+ self.get_group(group_id)
4944+ user_ref = self._get_user(user_id)
4945+ groups = set(user_ref.get('groups', []))
4946+ groups.add(group_id)
4947+ self.update_user(user_id, {'groups': list(groups)})
4948+
4949+ def check_user_in_group(self, user_id, group_id):
4950+ self.get_group(group_id)
4951+ user_ref = self._get_user(user_id)
4952+ if not group_id in set(user_ref.get('groups', [])):
4953+ raise exception.NotFound(_('User not found in group'))
4954+
4955+ def remove_user_from_group(self, user_id, group_id):
4956+ self.get_group(group_id)
4957+ user_ref = self._get_user(user_id)
4958+ groups = set(user_ref.get('groups', []))
4959+ try:
4960+ groups.remove(group_id)
4961+ except KeyError:
4962+ raise exception.NotFound(_('User not found in group'))
4963+ self.update_user(user_id, {'groups': list(groups)})
4964+
4965+ def list_users_in_group(self, group_id):
4966+ self.get_group(group_id)
4967+ user_keys = filter(lambda x: x.startswith("user-"), self.db.keys())
4968+ user_refs = [self.db.get(key) for key in user_keys]
4969+ user_refs_for_group = filter(lambda x: group_id in x['groups'],
4970+ user_refs)
4971+ return [identity.filter_user(x) for x in user_refs_for_group]
4972+
4973+ def list_groups_for_user(self, user_id):
4974+ user_ref = self._get_user(user_id)
4975+ group_ids = user_ref.get('groups', [])
4976+ return [self.get_group(x) for x in group_ids]
4977+
4978 def delete_user(self, user_id):
4979 try:
4980 old_user = self.db.get('user-%s' % user_id)
4981@@ -292,16 +336,21 @@
4982 self.db.delete('tenant_name-%s' % old_tenant['name'])
4983 self.db.delete('tenant-%s' % tenant_id)
4984
4985- def create_metadata(self, user_id, tenant_id, metadata):
4986- self.db.set('metadata-%s-%s' % (tenant_id, user_id), metadata)
4987- return metadata
4988-
4989- def update_metadata(self, user_id, tenant_id, metadata):
4990- self.db.set('metadata-%s-%s' % (tenant_id, user_id), metadata)
4991- return metadata
4992-
4993- def delete_metadata(self, user_id, tenant_id):
4994- self.db.delete('metadata-%s-%s' % (tenant_id, user_id))
4995+ def create_metadata(self, user_id, tenant_id, metadata,
4996+ domain_id=None, group_id=None):
4997+ if user_id:
4998+ self.db.set('metadata-%s-%s' % (tenant_id, user_id), metadata)
4999+ else:
5000+ self.db.set('metadata-%s-%s' % (tenant_id, group_id), metadata)
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches