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
=== modified file 'AUTHORS'
--- AUTHORS 2012-11-23 09:01:53 +0000
+++ AUTHORS 2013-01-25 16:27:23 +0000
@@ -40,6 +40,7 @@
40Doug Hellmann <doug.hellmann@dreamhost.com>40Doug Hellmann <doug.hellmann@dreamhost.com>
41Ed Leafe <ed@leafe.com>41Ed Leafe <ed@leafe.com>
42Édouard Thuleau <edouard1.thuleau@orange.com>42Édouard Thuleau <edouard1.thuleau@orange.com>
43Eduardo Patrocinio <epatro@gmail.com>
43Eoghan Glynn <eglynn@redhat.com>44Eoghan Glynn <eglynn@redhat.com>
44Everett Toews <everett.toews@gmail.com>45Everett Toews <everett.toews@gmail.com>
45Ewan Mellor <ewan.mellor@citrix.com>46Ewan Mellor <ewan.mellor@citrix.com>
@@ -64,6 +65,7 @@
64Joe Heck <heckj@mac.com>65Joe Heck <heckj@mac.com>
65Joe Savak <joe.savak@rackspace.com>66Joe Savak <joe.savak@rackspace.com>
66Johannes Erdfelt <johannes.erdfelt@rackspace.com>67Johannes Erdfelt <johannes.erdfelt@rackspace.com>
68John Bresnahan <jbresnah@redhat.com>
67John Dickinson <me@not.mn>69John Dickinson <me@not.mn>
68John Eo <john.eo@rackspace.com>70John Eo <john.eo@rackspace.com>
69John Eo <joon.eo@gmail.com>71John Eo <joon.eo@gmail.com>
@@ -85,6 +87,7 @@
85Lin Hua Cheng <lin-hua.cheng@hp.com>87Lin Hua Cheng <lin-hua.cheng@hp.com>
86long-wang <long.wang@bj.cs2c.com.cn>88long-wang <long.wang@bj.cs2c.com.cn>
87Mark Gius <mgius7096@gmail.com>89Mark Gius <mgius7096@gmail.com>
90Mark J. Washenberger <mark.washenberger@markwash.net>
88Mark McLoughlin <markmc@redhat.com>91Mark McLoughlin <markmc@redhat.com>
89Maru Newby <mnewby@internap.com>92Maru Newby <mnewby@internap.com>
90Michael Basnight <mbasnight@gmail.com>93Michael Basnight <mbasnight@gmail.com>
@@ -92,6 +95,7 @@
92Mohammed Naser <mnaser@vexxhost.com>95Mohammed Naser <mnaser@vexxhost.com>
93monsterxx03 <xyj.asmy@gmail.com>96monsterxx03 <xyj.asmy@gmail.com>
94Monty Taylor <mordred@inaugust.com>97Monty Taylor <mordred@inaugust.com>
98Nachiappan VR N <nachiappan.veerappan-nachiappan@hp.com>
95OpenStack Jenkins <jenkins@openstack.org>99OpenStack Jenkins <jenkins@openstack.org>
96Pádraig Brady <pbrady@redhat.com>100Pádraig Brady <pbrady@redhat.com>
97Pádraig Brady <P@draigBrady.com>101Pádraig Brady <P@draigBrady.com>
@@ -121,11 +125,13 @@
121Sirish Bitra <sirish.bitra@gmail.com>125Sirish Bitra <sirish.bitra@gmail.com>
122Sony K. Philip <sony@hcleai.com>126Sony K. Philip <sony@hcleai.com>
123Stef T <stelford@internap.com>127Stef T <stelford@internap.com>
128Steve Martinelli <stevemar@ca.ibm.com>
124Syed Armani <dce3062@gmail.com>129Syed Armani <dce3062@gmail.com>
125termie <github@anarkystic.com>130termie <github@anarkystic.com>
126Thierry Carrez <thierry@openstack.org>131Thierry Carrez <thierry@openstack.org>
127Tim Simpson <tim.simpson@rackspace.com>132Tim Simpson <tim.simpson@rackspace.com>
128Todd Willey <xtoddx@gmail.com>133Todd Willey <xtoddx@gmail.com>
134Tom Fifield <fifieldt@unimelb.edu.au>
129Unmesh Gurjar <unmesh.gurjar@nttdata.com>135Unmesh Gurjar <unmesh.gurjar@nttdata.com>
130Unmesh Gurjar <unmesh.gurjar@vertex.co.in>136Unmesh Gurjar <unmesh.gurjar@vertex.co.in>
131Vincent Hou <sbhou@cn.ibm.com>137Vincent Hou <sbhou@cn.ibm.com>
@@ -134,6 +140,7 @@
134vishvananda <vishvananda@gmail.com>140vishvananda <vishvananda@gmail.com>
135wanglong <wl3617@qq.com>141wanglong <wl3617@qq.com>
136Will Kelly <the.william.kelly@gmail.com>142Will Kelly <the.william.kelly@gmail.com>
143Wu Wenxiang <wu.wenxiang@99cloud.net>
137Yaguang Tang <heut2008@gmail.com>144Yaguang Tang <heut2008@gmail.com>
138Yogeshwar Srikrishnan <yoga80@yahoo.com>145Yogeshwar Srikrishnan <yoga80@yahoo.com>
139Yong Sheng Gong <gongysh@cn.ibm.com>146Yong Sheng Gong <gongysh@cn.ibm.com>
140147
=== modified file 'ChangeLog'
--- ChangeLog 2012-11-23 09:01:53 +0000
+++ ChangeLog 2013-01-25 16:27:23 +0000
@@ -1,3 +1,1005 @@
1commit 788f6c5ee60bea0146ae0f86a7aec9430654be8d
2Merge: 4fae928 3244451
3Author: Jenkins <jenkins@review.openstack.org>
4Date: Wed Jan 9 05:38:12 2013 +0000
5
6 Merge "Add missing .po files to tarball"
7
8commit 4fae928c59beaa558306a5aa3a3aa5c6f4945b70
9Author: Henry Nash <henryn@linux.vnet.ibm.com>
10Date: Thu Dec 13 16:48:13 2012 +0000
11
12 Keystone server support for user groups
13
14 This implements the server side of groups of users. This
15 set of code provides all the crud functionality for groups as
16 well as the corresponding support for role assignments.
17
18 blueprint user-groups
19
20 The following deficiencies existing with the current version and
21 will be corrected ahead of the final Grizzly release:
22
23 1) There is only placeholder support for LDAP (Bug #1092187)
24 2) Domain role grants are accepted but not yet honored (Bug #1093248)
25 3) Token invalidation does not occur with group changes (Bug #1093493)
26
27 This update also fills in missing v3 grant unit testing and v3 grant
28 support within the kvs backend. In addition, there is a fix for
29 Bug #1092200 (uncaught exception when listing grants)
30
31 DocImpact
32
33 Change-Id: Ibd1783b04b2d7804eff90312e5ef591dca4d0695
34
35 keystone/clean.py | 4 +
36 keystone/common/models.py | 17 +
37 .../migrate_repo/versions/013_add_group_tables.py | 93 +++++
38 keystone/config.py | 11 +
39 keystone/exception.py | 4 +
40 keystone/identity/backends/kvs.py | 201 ++++++++++-
41 keystone/identity/backends/ldap/core.py | 109 ++++++
42 keystone/identity/backends/pam.py | 3 -
43 keystone/identity/backends/sql.py | 362 +++++++++++++++++---
44 keystone/identity/controllers.py | 103 ++++--
45 keystone/identity/core.py | 113 +++++-
46 keystone/identity/routers.py | 67 +++-
47 keystone/service.py | 1 +
48 keystone/token/controllers.py | 70 +++-
49 tests/test_auth.py | 39 +++
50 tests/test_backend.py | 306 +++++++++++++++++
51 tests/test_backend_ldap.py | 47 +++
52 tests/test_sql_upgrade.py | 18 +-
53 tests/test_v3.py | 8 +
54 tests/test_v3_identity.py | 199 ++++++++++-
55 20 files changed, 1669 insertions(+), 106 deletions(-)
56
57commit 3244451c1beb2236c99e1bace5925e4953b6771e
58Author: Thierry Carrez <thierry@openstack.org>
59Date: Mon Jan 7 14:37:53 2013 +0100
60
61 Add missing .po files to tarball
62
63 Fix MANIFEST.in to include .po files in keystone/locale.
64 Fixes bug 1096063.
65
66 Change-Id: I4cf06a0777b5f22344ff18321bbf155f574b1e49
67
68 MANIFEST.in | 2 +-
69 1 file changed, 1 insertion(+), 1 deletion(-)
70
71commit 9460ff5c35809f4911cb5a1ee5f68d6351e797f4
72Merge: 2162e4b 64672bd
73Author: Jenkins <jenkins@review.openstack.org>
74Date: Sat Jan 5 23:33:29 2013 +0000
75
76 Merge "Upgrade WebOb to 1.2.3"
77
78commit 2162e4b3b54f99095aa0f5f6fc3cbcad20436cc4
79Merge: 2b08994 5a81be3
80Author: Jenkins <jenkins@review.openstack.org>
81Date: Sat Jan 5 23:25:14 2013 +0000
82
83 Merge "Removed unused imports"
84
85commit 2b08994e1f9d4ea7d7659faa014f541ed9a82e0e
86Merge: 863acc7 0e5533e
87Author: Jenkins <jenkins@review.openstack.org>
88Date: Fri Jan 4 22:29:31 2013 +0000
89
90 Merge "il8n some strings"
91
92commit 863acc7b6d39de3596e2bf767397774053156f45
93Merge: 76af49f 1f01d30
94Author: Jenkins <jenkins@review.openstack.org>
95Date: Thu Jan 3 19:30:53 2013 +0000
96
97 Merge "shorten pep8 output"
98
99commit 64672bdeb13097285af8dec16b6cacbef4495bab
100Author: Doug Hellmann <doug.hellmann@dreamhost.com>
101Date: Thu Jan 3 11:08:15 2013 -0500
102
103 Upgrade WebOb to 1.2.3
104
105 The version of WebOb being used in OpenStack was more than
106 1 year old. This change updates to the latest stable release.
107
108 Upgrading WebOb resolves a version conflict between OpenStack
109 and Pecan, the web framework used by the Ceilometer team for
110 version 2 of the ceilometer API.
111
112 Refer to http://docs.webob.org/en/latest/news.html
113 for the list of changes between 1.0.8 and 1.2.3.
114
115 bug 1092227
116
117 Change-Id: If68866122e6c492b03887af5953ab7cad01787ba
118 Signed-off-by: Doug Hellmann <doug.hellmann@dreamhost.com>
119
120 tools/pip-requires | 4 ++--
121 1 file changed, 2 insertions(+), 2 deletions(-)
122
123commit 0e5533eb6f828cffac1cdd98a524f69503332cec
124Author: Chuck Short <chuck.short@canonical.com>
125Date: Thu Jan 3 08:32:34 2013 -0600
126
127 il8n some strings
128
129 il8n some more missing strings.
130
131 Change-Id: I56d1d83093c8a5e895571e2d2db41c7600662754
132 Signed-off-by: Chuck Short <chuck.short@canonical.com>
133
134 keystone/common/controller.py | 14 +++++++-------
135 keystone/common/ldap/core.py | 16 ++++++++--------
136 keystone/common/sql/migration.py | 2 +-
137 keystone/common/utils.py | 4 ++--
138 keystone/identity/backends/ldap/core.py | 2 +-
139 5 files changed, 19 insertions(+), 19 deletions(-)
140
141commit 76af49f11a5cd2ef7be93c5cbe3244fe48cc6b31
142Author: OpenStack Jenkins <jenkins@openstack.org>
143Date: Wed Jan 2 00:00:46 2013 +0000
144
145 Imported Translations from Transifex
146
147 Change-Id: I94d6360ce6f6ca8150a83c12af887452bc4a41f6
148
149 keystone/locale/hu/LC_MESSAGES/keystone.po | 313 ++++++++++++++++++++++++++++
150 keystone/locale/keystone.pot | 18 +-
151 2 files changed, 324 insertions(+), 7 deletions(-)
152
153commit 5a81be30de7c756716aef06a361a88f553be9b76
154Author: Chuck Short <chuck.short@canonical.com>
155Date: Fri Dec 28 10:39:33 2012 -0600
156
157 Removed unused imports
158
159 Removed unused imports
160
161 Change-Id: I646d79849731b87ce6c1eeb80f42c77dd789ecff
162 Signed-off-by: Chuck Short <chuck.short@canonical.com>
163
164 keystone/cli.py | 4 ----
165 keystone/common/router.py | 1 -
166 .../versions/001_add_initial_tables.py | 1 -
167 .../sql/migrate_repo/versions/003_token_valid.py | 4 ----
168 .../migrate_repo/versions/006_add_policy_table.py | 1 -
169 .../migrate_repo/versions/007_add_domain_tables.py | 1 -
170 .../versions/008_normalize_identity.py | 3 ---
171 .../versions/009_normalize_identity_migration.py | 3 +--
172 .../sql/migrate_repo/versions/010_endpoints_v3.py | 1 -
173 .../versions/012_drop_legacy_endpoints.py | 1 -
174 setup.py | 1 -
175 tests/_ldap_livetest.py | 1 -
176 12 files changed, 1 insertion(+), 21 deletions(-)
177
178commit a0e06a8e96ccfeee1de0030da0a1a2ac9e6e5aad
179Author: Chuck Short <chuck.short@canonical.com>
180Date: Sat Dec 22 15:36:34 2012 -0600
181
182 Add pyflakes to tox.ini
183
184 Add the ability to use pyflakes.
185
186 Change-Id: I1c0a652258fd494bf6754b5b83c47166582a85d0
187 Signed-off-by: Chuck Short <chuck.short@canonical.com>
188
189 tools/flakes.py | 22 ++++++++++++++++++++++
190 tox.ini | 4 ++++
191 2 files changed, 26 insertions(+)
192
193commit daf3bdae226a76926a8a877e1ed4bd7046f9192d
194Merge: 1b3b642 0f22574
195Author: Jenkins <jenkins@review.openstack.org>
196Date: Mon Dec 24 03:46:16 2012 +0000
197
198 Merge "Adding a means to connect back to a pydevd debugger."
199
200commit 1b3b6428225d16162bcb9d44ab628bccd9f219b4
201Author: Chuck Short <chuck.short@canonical.com>
202Date: Sat Dec 22 18:09:13 2012 -0600
203
204 Fix spelling typo
205
206 Fixes spelling typo should be role_id instead of roll_id.
207
208 Change-Id: I45a994f7cbe3528ef5a9a667a67237c2a896db9c
209 Signed-off-by: Chuck Short <chuck.short@canonical.com>
210
211 keystone/identity/backends/ldap/core.py | 2 +-
212 1 file changed, 1 insertion(+), 1 deletion(-)
213
214commit 469ff6571e49f70662107a1db393b856214eea3c
215Merge: 4fb7ef4 e577cd6
216Author: Jenkins <jenkins@review.openstack.org>
217Date: Sat Dec 22 20:39:42 2012 +0000
218
219 Merge "Remove swift auth."
220
221commit 4fb7ef4faf0b0ef3077c0175d158df3ab601e4bf
222Merge: b5581fe 03eb280
223Author: Jenkins <jenkins@review.openstack.org>
224Date: Sat Dec 22 09:43:05 2012 +0000
225
226 Merge "Driver registry"
227
228commit 1f01d30983e3a67a146308ff8766f057bc5b7958
229Author: Adam Young <ayoung@redhat.com>
230Date: Thu Dec 20 21:43:41 2012 -0500
231
232 shorten pep8 output
233
234 This removes the PEP8 output that describes in detail how to fix each
235 problem. It makes pep8 review so long that the earliest lines scroll
236 out of the scrollback buffer before they can even be read.
237
238 With this change, each violation is on line long, which is
239 much more readable.
240
241 Change-Id: I0d8cc64fd6027419754732e314c047b3775a121c
242
243 run_tests.sh | 2 +-
244 1 file changed, 1 insertion(+), 1 deletion(-)
245
246commit 03eb2801a3ad38a39e9cf127c05ab710bf38ee1d
247Author: Dolph Mathews <dolph.mathews@rackspace.com>
248Date: Wed Dec 19 10:04:21 2012 -0600
249
250 Driver registry
251
252 Uses automatic dependency injection to provide controllers with driver
253 interfaces (identity_api, token_api, etc).
254
255 See tests/test_injection.py for a self-contained example.
256
257 Change-Id: I255087de534292fbf57a45b19f97488f831f607c
258
259 keystone/catalog/controllers.py | 11 ++-
260 keystone/catalog/core.py | 2 +
261 keystone/catalog/routers.py | 8 +-
262 keystone/common/controller.py | 10 +--
263 keystone/common/dependency.py | 67 +++++++++++++++++
264 keystone/contrib/admin_crud/core.py | 17 ++---
265 keystone/contrib/ec2/core.py | 17 ++---
266 keystone/contrib/user_crud/core.py | 11 +--
267 keystone/identity/controllers.py | 4 -
268 keystone/identity/core.py | 8 +-
269 keystone/identity/routers.py | 28 +++----
270 keystone/policy/core.py | 2 +
271 keystone/policy/routers.py | 4 +-
272 keystone/routers.py | 13 ++--
273 keystone/service.py | 32 ++++----
274 keystone/test.py | 22 ++++--
275 keystone/token/controllers.py | 2 +
276 keystone/token/core.py | 4 +-
277 keystone/token/routers.py | 6 +-
278 tests/test_auth.py | 14 +---
279 tests/test_injection.py | 141 +++++++++++++++++++++++++++++++++++
280 21 files changed, 297 insertions(+), 126 deletions(-)
281
282commit 0f225743e8644416df2f200d710912c40b7acd47
283Author: John Bresnahan <jbresnah@redhat.com>
284Date: Wed Dec 19 07:13:24 2012 -1000
285
286 Adding a means to connect back to a pydevd debugger.
287
288 That patch allows a developer to remotely run a pydev debugger and have the
289 keystone-all process connect back to it. Two command line options are
290 introduced:
291 --pydev-debug-host <host>
292 --pydev-debug-port <port>
293 both of the above options are required to enable this behavior.
294
295 This patch only enables this behavior when the service is started with
296 keystone-all. In the future parts of this patch can be used to enable
297 this behavior when running in Apache.
298
299 Change-Id: I92f99fa34112336a96e42e8261b7313f23ee994e
300
301 bin/keystone-all | 7 +++++++
302 keystone/common/utils.py | 19 +++++++++++++++++++
303 keystone/config.py | 3 +++
304 3 files changed, 29 insertions(+)
305
306commit b5581fea95f96dc7e43abe2b28c99678b5219238
307Merge: ac2d92c a591b30
308Author: Jenkins <jenkins@review.openstack.org>
309Date: Fri Dec 21 03:29:40 2012 +0000
310
311 Merge "add in pip requires for requests"
312
313commit a591b3010c37f19924775f52c8076778888f1ade
314Author: Adam Young <ayoung@redhat.com>
315Date: Thu Dec 20 16:40:20 2012 -0500
316
317 add in pip requires for requests
318
319 Change-Id: I0f5ac9a4008dc471cefea7a6ffe44d4c51950538
320
321 tools/pip-requires | 2 +-
322 tools/test-requires | 2 ++
323 2 files changed, 3 insertions(+), 1 deletion(-)
324
325commit ac2d92ca2eea1070f765be320acb62fd5bef6dd3
326Merge: 1a0d30b 2f85134
327Author: Jenkins <jenkins@review.openstack.org>
328Date: Tue Dec 18 18:01:40 2012 +0000
329
330 Merge "Split endpoint records in SQL by interface"
331
332commit 2f851340ee8969193b9dcc1913401aa9b33c5d97
333Author: Dolph Mathews <dolph.mathews@rackspace.com>
334Date: Fri Nov 30 12:52:26 2012 -0600
335
336 Split endpoint records in SQL by interface
337
338 This migrates the SQL backend such that v2 endpoints containing up to 3
339 URL's (public, internal and admin) stored in 'extra' are split into
340 unique endpoints.
341
342 Because legacy "endpoints" (each having publicUrl, internalUrl and
343 adminUrl) are no longer conceptually identical to v3's "endpoints" (each
344 having an interface and a url), new ID's are assigned to each entity and
345 each API continues to operate using with independent sets of endpoint
346 ID's.
347
348 Endpoints created on the v3 API are not exposed on the v2 API.
349
350 Change-Id: I2ba59d55907313ae65e908585fc49be0c4ce899a
351
352 keystone/catalog/backends/sql.py | 54 +++---
353 keystone/catalog/controllers.py | 65 ++++++-
354 .../sql/migrate_repo/versions/010_endpoints_v3.py | 54 ++++++
355 .../versions/011_populate_endpoint_type.py | 96 ++++++++++
356 .../versions/012_drop_legacy_endpoints.py | 51 ++++++
357 tests/test_backend.py | 3 +
358 tests/test_backend_sql.py | 78 ++++----
359 tests/test_sql_upgrade.py | 191 +++++++++++++++++---
360 tests/test_v3.py | 1 +
361 9 files changed, 487 insertions(+), 106 deletions(-)
362
363commit 1a0d30bf0173f8e03abeac4bda2e807bd4f29412
364Merge: 4f4b4a7 5b3a74d
365Author: Jenkins <jenkins@review.openstack.org>
366Date: Tue Dec 18 16:56:10 2012 +0000
367
368 Merge "Support non-default role_id_attribute"
369
370commit 4f4b4a7b5b0d846e308f2ce693d3c6e69f944d1e
371Merge: 7db702c f74aab2
372Author: Jenkins <jenkins@review.openstack.org>
373Date: Tue Dec 18 16:55:48 2012 +0000
374
375 Merge "Expand default time delta (bug 1089988)"
376
377commit 7db702cab1f2cad8160aeadc8c1ae27853b8a34c
378Merge: ede7e20 fb963a5
379Author: Jenkins <jenkins@review.openstack.org>
380Date: Tue Dec 18 14:43:26 2012 +0000
381
382 Merge "module refactoring"
383
384commit ede7e209bded5494a2453485e619b7b81f23cf3a
385Merge: 96d2ff7 23ba963
386Author: Jenkins <jenkins@review.openstack.org>
387Date: Mon Dec 17 23:54:12 2012 +0000
388
389 Merge "Fix typo s/interalurl/internalurl/"
390
391commit 96d2ff71ad01d53232cdc128df9d3b6109a04f67
392Merge: 7093c55 8e2a183
393Author: Jenkins <jenkins@review.openstack.org>
394Date: Mon Dec 17 21:45:00 2012 +0000
395
396 Merge "Test drivers return HTTP 501 Not Implemented"
397
398commit 7093c55d2e4722fc8ffdcef594cc5705b586a2d9
399Merge: 44e3c3e d17dfe6
400Author: Jenkins <jenkins@review.openstack.org>
401Date: Mon Dec 17 21:44:38 2012 +0000
402
403 Merge "Import pysqlite2 if sqlite3 is not available."
404
405commit 23ba963af45c0243d817ae38a84f9e3c830415eb
406Author: Mark J. Washenberger <mark.washenberger@markwash.net>
407Date: Mon Dec 17 13:41:39 2012 -0800
408
409 Fix typo s/interalurl/internalurl/
410
411 Change-Id: I9e9209731e5d13b21a7aff6127d932d69c457135
412
413 keystone/common/models.py | 2 +-
414 1 file changed, 1 insertion(+), 1 deletion(-)
415
416commit fb963a560939e6be8c98d74e5555de7283173e32
417Author: Adam Young <ayoung@redhat.com>
418Date: Wed Dec 12 13:17:54 2012 -0500
419
420 module refactoring
421
422 Distributes the functionality of service.py into the modules.
423 Moves ComposableRouters into the modules.
424 The routers and controllers now have short names.
425 The controllers get their APIs via the base class.
426
427 Change-Id: I87404b80ea9800d6792f97a7a3a64fe839065c1c
428
429 keystone/catalog/__init__.py | 1 +
430 keystone/catalog/controllers.py | 20 +-
431 keystone/catalog/routers.py | 25 ++
432 keystone/common/router.py | 57 +++++
433 keystone/contrib/admin_crud/core.py | 18 +-
434 keystone/contrib/user_crud/core.py | 23 +-
435 keystone/controllers.py | 144 +++++++++++
436 keystone/identity/controllers.py | 24 +-
437 keystone/identity/routers.py | 73 +++++-
438 keystone/policy/__init__.py | 1 +
439 keystone/policy/routers.py | 22 ++
440 keystone/routers.py | 68 +++++
441 keystone/service.py | 472 ++---------------------------------
442 keystone/token/__init__.py | 1 +
443 keystone/token/routers.py | 61 +++++
444 15 files changed, 503 insertions(+), 507 deletions(-)
445
446commit 44e3c3ece3f6e8a596dbec37476d8fb5c85d6f6c
447Merge: ebfbd6c e093e81
448Author: OpenStack Jenkins <jenkins@openstack.org>
449Date: Fri Dec 14 20:13:31 2012 +0000
450
451 Merge "Imported Translations from Transifex"
452
453commit ebfbd6c0844f9ab3e9a864112672164cf8b3696f
454Merge: d939d16 be3dcf9
455Author: Jenkins <jenkins@review.openstack.org>
456Date: Fri Dec 14 20:13:10 2012 +0000
457
458 Merge "Test for content-type appropriate 404 (bug 1089987)"
459
460commit d939d16e747b4a2c5db1f1fdda93a01b79fe6e83
461Merge: f5d26ea 18a49ae
462Author: Jenkins <jenkins@review.openstack.org>
463Date: Fri Dec 14 15:20:07 2012 +0000
464
465 Merge "syncing run_tests to match tox"
466
467commit f5d26ea9c67e2bb812f0e7a36512538b9f3e18ff
468Merge: 5b7160c 6ceb066
469Author: Jenkins <jenkins@review.openstack.org>
470Date: Fri Dec 14 15:04:46 2012 +0000
471
472 Merge "fixing bug 1046862"
473
474commit be3dcf9873fb84bbb5c2cd3ed8f36444f353757e
475Author: Dolph Mathews <dolph.mathews@rackspace.com>
476Date: Thu Dec 13 10:01:21 2012 -0600
477
478 Test for content-type appropriate 404 (bug 1089987)
479
480 Change-Id: Idfba75f90e38de315ec50e660932beb8243f76f8
481
482 keystone/common/wsgi.py | 2 +-
483 tests/test_content_types.py | 12 ++++++++++++
484 2 files changed, 13 insertions(+), 1 deletion(-)
485
486commit e093e81c750408478d74fafac2cb0cc7eb221d5f
487Author: OpenStack Jenkins <jenkins@openstack.org>
488Date: Fri Dec 14 00:01:05 2012 +0000
489
490 Imported Translations from Transifex
491
492 Change-Id: Ib2cb912443034b4d9855441ca83d103e2a9bdbe8
493
494 keystone/locale/keystone.pot | 276 +++++++++++++++++++++++++++++++++++++++++-
495 1 file changed, 275 insertions(+), 1 deletion(-)
496
497commit 5b7160cd536f0a86cf33bc294679bd19a2e90549
498Merge: 4e2be8a e4d61ac
499Author: Jenkins <jenkins@review.openstack.org>
500Date: Thu Dec 13 22:11:33 2012 +0000
501
502 Merge "Add tests for contrib.s3.core."
503
504commit 6ceb06689f5f1da26584192ae9f46a5248277565
505Author: Steve Martinelli <stevemar@ca.ibm.com>
506Date: Thu Dec 13 11:35:01 2012 -0500
507
508 fixing bug 1046862
509
510 adding message to readme.rst to include openSSL dependency
511
512 fixing bug 1046862
513
514 Change-Id: Iff1fbc95e804f9e4ddc74ea38c553426c4eabb33
515
516 README.rst | 7 +++++++
517 1 file changed, 7 insertions(+)
518
519commit f74aab2463ccc9549c07175ed82015f23ad2694c
520Author: Dolph Mathews <dolph.mathews@rackspace.com>
521Date: Thu Dec 13 09:42:32 2012 -0600
522
523 Expand default time delta (bug 1089988)
524
525 Change-Id: I3d08092bf5248f75b238591586443a4daea02a20
526
527 keystone/test.py | 9 ++++++---
528 1 file changed, 6 insertions(+), 3 deletions(-)
529
530commit e4d61ac6a7893743ff47c0a69529c5f21f249127
531Author: Chmouel Boudjnah <chmouel@chmouel.com>
532Date: Wed Dec 12 19:04:23 2012 +0100
533
534 Add tests for contrib.s3.core.
535
536 Change-Id: I0a5ea82dcbcf29f6581d8c69e8961138fa019145
537
538 tests/test_contrib_s3_core.py | 54 +++++++++++++++++++++++++++++++++++++++++
539 1 file changed, 54 insertions(+)
540
541commit 8e2a183992311fe005abbfaa40d68dd7ce1fffd3
542Author: Dolph Mathews <dolph.mathews@rackspace.com>
543Date: Mon Dec 10 10:10:22 2012 -0600
544
545 Test drivers return HTTP 501 Not Implemented
546
547 Change-Id: I4cd21022593e6b4c3965edd00ecea01a00584516
548
549 keystone/policy/core.py | 2 +-
550 keystone/token/backends/kvs.py | 14 +++++-----
551 keystone/token/backends/memcache.py | 8 +++---
552 keystone/token/backends/sql.py | 8 +++---
553 keystone/token/controllers.py | 5 ++--
554 keystone/token/core.py | 44 ++++++++++++++++-------------
555 tests/test_drivers.py | 52 +++++++++++++++++++++++++++++++++++
556 7 files changed, 96 insertions(+), 37 deletions(-)
557
558commit 5b3a74d56a376afed64dd2515c4aa59995187433
559Author: Dolph Mathews <dolph.mathews@rackspace.com>
560Date: Wed Dec 12 15:01:04 2012 -0600
561
562 Support non-default role_id_attribute
563
564 As is, a default value of 'cn' is hardcoded as the attribute name (which
565 also happens to be the default value in keystone.config) used for role
566 grants, revokes, etc.
567
568 Change-Id: Ic36e6d726e2dc48714703c2dd7a433f3d34b78b1
569
570 keystone/identity/backends/ldap/core.py | 3 ++-
571 1 file changed, 2 insertions(+), 1 deletion(-)
572
573commit e577cd60871e1810b45236d3642d60e460dc4858
574Author: Chmouel Boudjnah <chmouel@chmouel.com>
575Date: Sat Dec 8 13:38:45 2012 +0100
576
577 Remove swift auth.
578
579 - This has been moved since last release to swift main repository.
580
581 Change-Id: I11fc4001fbc4a1d78823d41450cdfcc97677c420
582
583 doc/source/configuringservices.rst | 147 +----------------
584 keystone/middleware/swift_auth.py | 295 -----------------------------------
585 tests/test_swift_auth_middleware.py | 249 -----------------------------
586 3 files changed, 2 insertions(+), 689 deletions(-)
587
588commit 4e2be8a8880f03b1c6d1dc663d7259dbb45ddf67
589Author: Dolph Mathews <dolph.mathews@rackspace.com>
590Date: Tue Dec 11 14:40:27 2012 -0600
591
592 Move token controller into keystone.token
593
594 Change-Id: Ie8277529185f645854e0aebaafa173c06a7c5164
595
596 keystone/common/controller.py | 12 +-
597 keystone/contrib/ec2/core.py | 5 +-
598 keystone/service.py | 556 ++---------------------------------------
599 keystone/token/__init__.py | 1 +
600 keystone/token/controllers.py | 545 ++++++++++++++++++++++++++++++++++++++++
601 tests/test_auth.py | 358 ++++++++++++++++++++++++++
602 tests/test_service.py | 355 --------------------------
603 7 files changed, 927 insertions(+), 905 deletions(-)
604
605commit 6397580a52be5288b4cb5e0a86a8c340fe4fd0ae
606Merge: bf4b9f4 0ea864b
607Author: Jenkins <jenkins@review.openstack.org>
608Date: Tue Dec 11 14:03:52 2012 +0000
609
610 Merge "Adding downgrade steps for migration scripts."
611
612commit d17dfe65550d393739dc50a1eedfe65903a81d28
613Author: Yuriy Taraday <yorik.sar@gmail.com>
614Date: Fri Dec 7 22:32:52 2012 +0400
615
616 Import pysqlite2 if sqlite3 is not available.
617
618 Otherwise test_import_legacy fails on import.
619
620 Change-Id: I902493f5b726f5bc9e23e776598b8938c85e622c
621
622 tests/test_import_legacy.py | 8 +++++---
623 1 file changed, 5 insertions(+), 3 deletions(-)
624
625commit bf4b9f49878e85000b197ea9c2627cc67fda5cdb
626Merge: d159c61 aaf61a4
627Author: Jenkins <jenkins@review.openstack.org>
628Date: Mon Dec 10 22:14:15 2012 +0000
629
630 Merge "Remove mentions of essex in docs (bug 1085247)"
631
632commit d159c616fd52436760242d3254c8bdb54810bcb4
633Merge: a800fae 847d591
634Author: Jenkins <jenkins@review.openstack.org>
635Date: Mon Dec 10 21:44:54 2012 +0000
636
637 Merge "Port to argparse based cfg"
638
639commit aaf61a4fc9d07a73d2a31abb097a2d862598c4e5
640Author: Eduardo Patrocinio <epatro@gmail.com>
641Date: Tue Dec 4 15:11:16 2012 -0500
642
643 Remove mentions of essex in docs (bug 1085247)
644
645 Change-Id: I663e9317c2b5eb5fe7190ea6c656fcebff7078fd
646
647 doc/source/configuration.rst | 20 ++++++++++----------
648 1 file changed, 10 insertions(+), 10 deletions(-)
649
650commit a800fae22c627e89a09ffc35b95dd072416da14a
651Author: Brian Waldon <brian.waldon@rackspace.com>
652Date: Thu Dec 6 12:31:51 2012 -0800
653
654 Ensure serviceCatalog is list when empty, not dict
655
656 Fixes bug 1087405.
657
658 Change-Id: I152c7f418a66ccfe541e26efe75b59bffa6c3849
659
660 keystone/service.py | 2 +-
661 tests/test_content_types.py | 19 +++++++++++++++++--
662 2 files changed, 18 insertions(+), 3 deletions(-)
663
664commit 0ea864b26e6e2e9be44785af61fd90a9b13b5265
665Author: Justin Shepherd <jshepher@rackspace.com>
666Date: Mon Nov 26 17:37:02 2012 +0000
667
668 Adding downgrade steps for migration scripts.
669
670 Also updated test_sql_upgrade to check the actions from 007_add_domain_tables.
671
672 Fixes: bug #1081167
673
674 Change-Id: I194c7de9ae8a3bb8f2f9f37d3a91f4fac2fe2913
675
676 .../versions/001_add_initial_tables.py | 9 +++++++-
677 .../migrate_repo/versions/003_sqlite_downgrade.sql | 1 -
678 .../migrate_repo/versions/006_add_policy_table.py | 6 ++++-
679 .../migrate_repo/versions/007_add_domain_tables.py | 5 ++++
680 tests/test_sql_upgrade.py | 24 ++++++++++++++++++++
681 5 files changed, 42 insertions(+), 3 deletions(-)
682
683commit 7978bb271bf0e978a095aa088e4bb2bdb1d684f8
684Merge: 3583946 84a0b2d
685Author: Jenkins <jenkins@review.openstack.org>
686Date: Wed Dec 5 21:21:39 2012 +0000
687
688 Merge "Bug 1075090 -- Fixing log messages in python source code to support internationalization."
689
690commit 3583946d933b989b14c25daa9d6c462142eb400f
691Merge: 9b529c8 c858c1b
692Author: Jenkins <jenkins@review.openstack.org>
693Date: Wed Dec 5 21:08:07 2012 +0000
694
695 Merge "Only 'import *' from 'core' modules"
696
697commit 9b529c8c00fc344d5a5e33170e95ba5f1bee0fed
698Merge: 8c15e3e 77dee93
699Author: Jenkins <jenkins@review.openstack.org>
700Date: Wed Dec 5 21:07:51 2012 +0000
701
702 Merge "use keystone test and change config during setUp"
703
704commit 847d5912d383072e3c38d6d19fce15981ca3110a
705Author: Mark McLoughlin <markmc@redhat.com>
706Date: Mon Nov 26 14:39:49 2012 +0000
707
708 Port to argparse based cfg
709
710 Sync the following changes from oslo-incubator:
711
712 3557d84 Fix ListOpt to trim whitespace
713 01ab910 Fix set_default() with boolean CLI options
714 af18eaa Improve cfg's argparse sub-parsers support
715 f21e1d9 Fix regression with cfg CLI arguments
716 ceb4aa7 Fix broken --help with CommonConfigOpts
717 5e9503b Hide the GroupAttr conf and group attributes
718 b6d24bb updating sphinx documentation
719 403509e Don't reference argparse._StoreAction
720 e17deb8 Fix minor coding style issue
721 0c29e1d Remove ConfigCliParser class
722 5b9cb41 Add support for positional arguments
723 dbc72a6 Use stock argparse behaviour for optional args
724 768a147 Use stock argparse --usage behaviour
725 ac180b9 Use stock argparse --version behaviour
726 0787e38 Remove add_option() method
727 5afead0 Completely remove cfg's disable_interspersed_args()
728 5f564b2 argparse support for cfg
729 d7b6397 Add a missing comma in a docstring.
730 aca1805 cfg: fix required if option has a dash
731
732 The main API change affecting keystone is that CONF() no longer returns
733 unparsed arguments. The keystone-manage command is updated to use
734 argparse sub-parsers to achieve the same effect.
735
736 Change-Id: Ie8972ce851f1247d8710e9e0611bb3e2f843cb45
737
738 keystone/cli.py | 133 +++++------
739 keystone/openstack/common/cfg.py | 451 ++++++++++++++++++++++++--------------
740 2 files changed, 345 insertions(+), 239 deletions(-)
741
742commit c858c1b304cae6310f08a220cf54c763f684fc42
743Author: Dolph Mathews <dolph.mathews@rackspace.com>
744Date: Wed Dec 5 09:58:54 2012 -0600
745
746 Only 'import *' from 'core' modules
747
748 - Renamed identity.controllers.* and identity.routers.* since they
749 now occopy unique namespaces (thanks ayoung!)
750 - Moved catalog and policy controllers into their own respective modules
751
752 Change-Id: Ib9e277355e0eac15d4d218785c816b718b493b5b
753
754 HACKING.rst | 2 +-
755 keystone/catalog/__init__.py | 1 +
756 keystone/catalog/controllers.py | 154 +++++++++++++++++++++++++++++++++++
757 keystone/catalog/core.py | 136 -------------------------------
758 keystone/contrib/admin_crud/core.py | 10 +--
759 keystone/contrib/user_crud/core.py | 11 ++-
760 keystone/identity/__init__.py | 4 +-
761 keystone/identity/controllers.py | 28 +++----
762 keystone/identity/routers.py | 25 ++----
763 keystone/policy/__init__.py | 1 +
764 keystone/policy/controllers.py | 48 +++++++++++
765 keystone/policy/core.py | 32 --------
766 keystone/service.py | 20 ++---
767 13 files changed, 246 insertions(+), 226 deletions(-)
768
769commit 77dee93763e4941b07f628c1c67d925503a5df51
770Author: Ionuț Arțăriși <iartarisi@suse.cz>
771Date: Mon Dec 3 11:59:20 2012 +0100
772
773 use keystone test and change config during setUp
774
775 Also fixes this traceback which I keep getting on devstack:
776
777 ERROR: test_create_certs (tests.test_cert_setup.CertSetupTestCase)
778 ----------------------------------------------------------------------
779 Traceback (most recent call last):
780 File "/opt/stack/keystone/tests/test_cert_setup.py", line 52, in tearDown
781 shutil.rmtree(rootdir(SSLDIR))
782 File "/usr/lib/python2.7/shutil.py", line 237, in rmtree
783 onerror(os.listdir, path, sys.exc_info())
784 File "/usr/lib/python2.7/shutil.py", line 235, in rmtree
785 names = os.listdir(path)
786 OSError: [Errno 2] No such file or directory: '/opt/stack/keystone/tests/ssl/'
787
788 Fixes bug 1086812
789
790 Change-Id: Iba10822aaf1284549d610bb1172df03ffc48f363
791
792 tests/test_cert_setup.py | 16 +++++++++-------
793 1 file changed, 9 insertions(+), 7 deletions(-)
794
795commit 84a0b2df5932fabb0cdaaaddeb86d1f55a7ac06e
796Author: Nachiappan VR N <nachiappan.veerappan-nachiappan@hp.com>
797Date: Wed Nov 14 10:01:59 2012 -0800
798
799 Bug 1075090 -- Fixing log messages in python source code to support internationalization.
800
801 Change-Id: I6b50abaa82effad8feaaac8d85086ca8b5d42590
802
803 keystone/catalog/backends/templated.py | 2 +-
804 keystone/catalog/core.py | 16 +++++-----
805 keystone/clean.py | 13 ++++----
806 keystone/common/bufferedhttp.py | 4 +--
807 keystone/common/cms.py | 4 +--
808 keystone/common/ldap/core.py | 17 +++++-----
809 keystone/common/ldap/fakeldap.py | 54 +++++++++++++++++---------------
810 keystone/common/sql/core.py | 2 +-
811 keystone/common/sql/legacy.py | 2 +-
812 keystone/common/sql/nova.py | 14 ++++-----
813 keystone/common/utils.py | 10 +++---
814 keystone/common/wsgi.py | 6 ++--
815 keystone/config.py | 4 +--
816 keystone/policy/backends/rules.py | 2 +-
817 keystone/test.py | 2 +-
818 15 files changed, 80 insertions(+), 72 deletions(-)
819
820commit 8c15e3eba68d4af655eacee3d1ec46e98911d119
821Author: Alvaro Lopez Garcia <aloga@ifca.unican.es>
822Date: Mon Dec 3 10:12:06 2012 +0100
823
824 Added documentation for the external auth support
825
826 This covers given authentication using REMOTE_USER and also the way to
827 implement custom auth with WSGI middleware.
828
829 DocImpact
830 blueprint: pluggable-identity-authentication-handlers
831 Change-Id: Idbac8c38d1f0be1febbbc8056c929bada6bbb07e
832
833 doc/source/external-auth.rst | 117 ++++++++++++++++++++++++++++++++++++++++++
834 doc/source/index.rst | 1 +
835 2 files changed, 118 insertions(+)
836
837commit 75277cf1ae496145369e929702005ef2304e6942
838Merge: 5b73757 af8761d
839Author: Jenkins <jenkins@review.openstack.org>
840Date: Mon Dec 3 09:57:36 2012 +0000
841
842 Merge "check the redirected path on the request, not the response"
843
844commit af8761d9e0add62a83604b77ab015f5a8b3120a9
845Author: Ionuț Arțăriși <iartarisi@suse.cz>
846Date: Fri Nov 30 14:04:04 2012 +0100
847
848 check the redirected path on the request, not the response
849
850 The request object's path changes when it gets redirected. This
851 behaviour is in tune with the latest WebOb code as well as the
852 old. The response environ defaults to None in WebOb >= 1.2b1
853 http://docs.webob.org/en/latest/news.html#b1
854
855 Change-Id: I557563ce5407a8ef1b5dae680e456e589285be25
856
857 tests/test_s3_token_middleware.py | 8 ++++----
858 1 file changed, 4 insertions(+), 4 deletions(-)
859
860commit 5b73757de94a30b7cc8566e2bf429c1aecd5c320
861Author: Wu Wenxiang <wu.wenxiang@99cloud.net>
862Date: Thu Nov 29 23:58:04 2012 +0800
863
864 Validate password type (bug 1081861)
865
866 Raise keystone.exception.ValidationError when password type was not string
867
868 Change-Id: Ib7538806777db0fe3a3cf9f22bf06a1d505c232f
869
870 keystone/common/utils.py | 12 ++++++++----
871 1 file changed, 8 insertions(+), 4 deletions(-)
872
873commit f57098df8e50fae95c2c532407ec5bc6a10205e1
874Author: Adam Young <ayoung@redhat.com>
875Date: Wed Nov 28 17:27:43 2012 -0500
876
877 split identities module into logical parts
878 remove unneeded imports from core
879
880 Change-Id: I02fc2439cc115878d8081e052faf9ff96d20f6ec
881
882 keystone/identity/__init__.py | 2 +
883 keystone/identity/controllers.py | 607 +++++++++++++++++++++++++++++++++++++
884 keystone/identity/core.py | 614 --------------------------------------
885 keystone/identity/routers.py | 72 +++++
886 4 files changed, 681 insertions(+), 614 deletions(-)
887
888commit 38c7e46a640a94da4da89a39a5a1ea9c081f1eb5
889Author: Dolph Mathews <dolph.mathews@rackspace.com>
890Date: Wed Nov 28 10:28:07 2012 -0500
891
892 Ensure token expiration is maintained (bug 1079216)
893
894 Change-Id: I95853ec36e9c4cd937cfac7e08b648e830f9efd0
895
896 keystone/service.py | 1 +
897 tests/test_service.py | 57 +++++++++++++++++++++++++++++++++++++++++++++++++
898 2 files changed, 58 insertions(+)
899
900commit ede63fbfe504cffb4b29f7394b1bf4872d093588
901Merge: d970e5f 1012bd4
902Author: Jenkins <jenkins@review.openstack.org>
903Date: Tue Nov 27 19:49:22 2012 +0000
904
905 Merge "normalize identity"
906
907commit 1012bd42df5906bca67a82663f23b5c8a4eafe68
908Author: Adam Young <ayoung@redhat.com>
909Date: Tue Nov 6 17:16:56 2012 -0500
910
911 normalize identity
912
913 modify tables by adding columns, and modify entities
914 by adding attributes for password, description and enabled
915
916 update tests to deal with change from 'False' and 'True' to the
917 python values False and True
918
919 Added a Text type from SQL Alchemy
920
921 Bug 1070351
922 Bug 1023544
923
924 Change-Id: I066c788b5d08a8f42a9b5412ea9e29e4fe9ba205
925
926 keystone/common/sql/core.py | 1 +
927 .../versions/008_normalize_identity.py | 61 ++++++++
928 .../migrate_repo/versions/008_sqlite_downgrade.sql | 5 +
929 .../versions/009_normalize_identity_migration.py | 146 ++++++++++++++++++++
930 keystone/identity/backends/sql.py | 8 +-
931 tests/default_fixtures.py | 8 ++
932 tests/test_backend.py | 18 +--
933 tests/test_backend_sql.py | 2 +
934 tests/test_sql_upgrade.py | 53 ++++++-
935 9 files changed, 290 insertions(+), 12 deletions(-)
936
937commit d970e5f815558706e5be642d814d08c93b0dd42a
938Merge: 3779c67 d4c4cf0
939Author: Jenkins <jenkins@review.openstack.org>
940Date: Tue Nov 27 04:22:51 2012 +0000
941
942 Merge "Fixes typo in keystone setup doc"
943
944commit d4c4cf035120c22c222b16c963abb1b82c33a707
945Author: Tom Fifield <fifieldt@unimelb.edu.au>
946Date: Tue Nov 27 12:38:07 2012 +1000
947
948 Fixes typo in keystone setup doc
949
950 fixes bug 1083391
951
952 A one character change to fix a typo in setup doc, reported
953 by a user :s
954
955 Change-Id: I4fefec089c9ded4b773f4b3641e30162a4faa2f8
956
957 doc/source/setup.rst | 2 +-
958 1 file changed, 1 insertion(+), 1 deletion(-)
959
960commit 3779c675c54fbc2be9d341e2a2a77b520f0f3a59
961Author: OpenStack Jenkins <jenkins@openstack.org>
962Date: Tue Nov 27 00:01:43 2012 +0000
963
964 Imported Translations from Transifex
965
966 Change-Id: I2cb4f8bd3891b474413eef11aae62188b358d359
967
968 keystone/locale/keystone.pot | 10 +---------
969 1 file changed, 1 insertion(+), 9 deletions(-)
970
971commit 904af119d2b84a93e416b7b297eda3b321840669
972Author: Mark McLoughlin <markmc@redhat.com>
973Date: Mon Nov 26 16:16:54 2012 +0000
974
975 Stop using cfg's internal implementation details
976
977 The fact that a cfg opt register using register_opt() is available via
978 the command line is actually a bug (see bug #1082279).
979
980 Also, using the _cli_values attribute is clearly poking into private
981 implementation details.
982
983 Fix both issues by registering the opt using register_cli_opt() and
984 accessing its value the normal way.
985
986 Change-Id: If170dcd96daae5b4c3d7cdebed914df417c2209b
987
988 bin/keystone-all | 2 +-
989 keystone/config.py | 4 +++-
990 2 files changed, 4 insertions(+), 2 deletions(-)
991
992commit 18a49ae5767cc9cf0f81d3bb9616aba4f076178a
993Author: Joe Heck <heckj@mac.com>
994Date: Wed Nov 21 22:02:19 2012 +0000
995
996 syncing run_tests to match tox
997
998 Change-Id: Ide81b1ea9230ceb2ad463d4f253eb7021fc683da
999
1000 run_tests.sh | 2 +-
1001 1 file changed, 1 insertion(+), 1 deletion(-)
1002
1commit 07c1aafdf20db6d6d7c0d3e15074bc02e2f1d2aa1003commit 07c1aafdf20db6d6d7c0d3e15074bc02e2f1d2aa
2Merge: d8aa7fd 01fccdb1004Merge: d8aa7fd 01fccdb
3Author: Jenkins <jenkins@review.openstack.org>1005Author: Jenkins <jenkins@review.openstack.org>
41006
=== modified file 'HACKING.rst'
--- HACKING.rst 2012-11-02 13:48:49 +0000
+++ HACKING.rst 2013-01-25 16:27:23 +0000
@@ -44,7 +44,7 @@
44Imports44Imports
45-------45-------
4646
47- Do not import objects, only modules47- Import modules, not module attributes
48- Do not import more than one module per line48- Do not import more than one module per line
49- Do not make relative imports49- Do not make relative imports
50- Order your imports by the full module path50- Order your imports by the full module path
5151
=== modified file 'MANIFEST.in'
--- MANIFEST.in 2012-08-16 13:59:29 +0000
+++ MANIFEST.in 2013-01-25 16:27:23 +0000
@@ -18,5 +18,5 @@
18graft tests18graft tests
19graft tools19graft tools
20graft examples20graft examples
21recursive-include keystone *.json *.xml *.cfg *.pem README *.pot *.sql21recursive-include keystone *.json *.xml *.cfg *.pem README *.po *.pot *.sql
22global-exclude *.pyc *.sdx *.log *.db *.swp22global-exclude *.pyc *.sdx *.log *.db *.swp
2323
=== modified file 'README.rst'
--- README.rst 2012-05-24 14:04:20 +0000
+++ README.rst 2013-01-25 16:27:23 +0000
@@ -212,3 +212,10 @@
212212
213In the backend this would look up the policy for 'action:nova:add_network' and213In the backend this would look up the policy for 'action:nova:add_network' and
214then do what is effectively a 'Simple Match' style match against the creds.214then do what is effectively a 'Simple Match' style match against the creds.
215
216
217----------------------------------
218Dependencies
219----------------------------------
220
221Ensure an OpenSSL version of 1.0+ is installed.
215\ No newline at end of file222\ No newline at end of file
216223
=== modified file 'bin/keystone-all'
--- bin/keystone-all 2012-11-02 13:48:49 +0000
+++ bin/keystone-all 2013-01-25 16:27:23 +0000
@@ -90,7 +90,14 @@
90 CONF.print_help()90 CONF.print_help()
91 sys.exit(1)91 sys.exit(1)
9292
93 monkeypatch_thread = not CONF._cli_values['standard_threads']93 monkeypatch_thread = not CONF.standard_threads
94 pydev_debug_url = utils.setup_remote_pydev_debug()
95 if pydev_debug_url:
96 # in order to work around errors caused by monkey patching we have to
97 # set the thread to False. An explanation is here:
98 # http://lists.openstack.org/pipermail/openstack-dev/2012-August/
99 # 000794.html
100 monkeypatch_thread = False
94 eventlet.patcher.monkey_patch(all=False, socket=True, time=True,101 eventlet.patcher.monkey_patch(all=False, socket=True, time=True,
95 thread=monkeypatch_thread)102 thread=monkeypatch_thread)
96103
97104
=== modified file 'debian/changelog'
--- debian/changelog 2012-11-26 19:24:17 +0000
+++ debian/changelog 2013-01-25 16:27:23 +0000
@@ -1,3 +1,36 @@
1keystone (2013.1~g2-0ubuntu1~cloud0) precise-grizzly; urgency=low
2
3 * New upstream release for the Ubuntu Cloud Archive.
4
5 -- Chuck Short <zulcss@ubuntu.com> Wed, 23 Jan 2013 12:27:47 -0600
6
7keystone (2013.1~g2-0ubuntu1) raring; urgency=low
8
9 [ James Page ]
10 * Re-enable gating of package build based on successful unit testing:
11 - d/tests/test_overrides.conf: Fixup test configuration to use
12 correct certificate locations.
13 - d/p/fix-ubuntu-tests.patch: Skip tests for older versions of
14 keystoneclient based on checkouts of upstream git repo.
15 - d/rules: Re-enable package build failure on test failure.
16 * d/control: Bump dependencies on python-keystoneclient to >= 1:0.2.
17 * d/control: Update Vcs-Bzr location to point to correct branch.
18 * d/control,d/po/*: Setup package templates for translation.
19 * d/man/*: Corrected spellings in man pages.
20 * d/keystone.upstart: Tweak 'stop on' to be triggered on all
21 appropriate runlevel transitions, use start-stop-daemon to startup
22 keystone daemon.
23
24 [ Adam Gandelman ]
25 * debian/keystone.manpages: Install sphinx-generated manpages instead
26 of our own outdated and unneeded versions. (LP: #1082050)
27
28 [ Chuck Short ]
29 * New upstream release.
30 * Remove incomplete/broken dbconfig-common scripts.
31
32 -- Chuck Short <zulcss@ubuntu.com> Fri, 11 Jan 2013 08:47:26 -0600
33
1keystone (2013.1~g1-0ubuntu1~cloud0) precise-grizzly; urgency=low34keystone (2013.1~g1-0ubuntu1~cloud0) precise-grizzly; urgency=low
235
3 * New upstream release for the Ubuntu Cloud Archive.36 * New upstream release for the Ubuntu Cloud Archive.
437
=== modified file 'debian/control'
--- debian/control 2012-11-02 13:48:49 +0000
+++ debian/control 2013-01-25 16:27:23 +0000
@@ -6,11 +6,12 @@
6Uploaders: Soren Hansen <soren@ubuntu.com>6Uploaders: Soren Hansen <soren@ubuntu.com>
7Build-Depends: debhelper (>= 7.0.50),7Build-Depends: debhelper (>= 7.0.50),
8 pep8,8 pep8,
9 po-debconf,
9 pylint,10 pylint,
10 python-all (>= 2.6),11 python-all (>= 2.6),
11 python-all-dev (>= 2.6.6-3~) | python-support,12 python-all-dev (>= 2.6.6-3~) | python-support,
12 python-eventlet,13 python-eventlet,
13 python-keystoneclient ( >= 1:0.1.3 ),14 python-keystoneclient ( >= 1:0.2 ),
14 python-ldap,15 python-ldap,
15 python-lxml,16 python-lxml,
16 python-memcache,17 python-memcache,
@@ -33,7 +34,7 @@
33Standards-Version: 3.9.334Standards-Version: 3.9.3
34XS-Python-Version: >= 2.635XS-Python-Version: >= 2.6
35Homepage: http://launchpad.net/keystone36Homepage: http://launchpad.net/keystone
36Vcs-Bzr: https://code.launchpad.net/~ubuntu-server-dev/keystone/essex37Vcs-Bzr: https://code.launchpad.net/~openstack-ubuntu-testing/keystone/grizzly
3738
38Package: python-keystone39Package: python-keystone
39Architecture: all40Architecture: all
@@ -52,7 +53,7 @@
52 python-sqlalchemy,53 python-sqlalchemy,
53 python-migrate,54 python-migrate,
54 python-prettytable,55 python-prettytable,
55 python-keystoneclient ( >= 1:0.1.3 ),56 python-keystoneclient ( >= 1:0.2 ),
56 python-webob,57 python-webob,
57 python-iso860158 python-iso8601
58Suggests: python-memcache59Suggests: python-memcache
@@ -76,8 +77,7 @@
76Depends: ${python:Depends}, ${misc:Depends},77Depends: ${python:Depends}, ${misc:Depends},
77 python-keystone (= ${source:Version}),78 python-keystone (= ${source:Version}),
78 adduser,79 adduser,
79 ssl-cert (>= 1.0.12),80 ssl-cert (>= 1.0.12)
80 dbconfig-common
81Description: OpenStack identity service - Daemons81Description: OpenStack identity service - Daemons
82 Keystone is a proposed independent authentication service for OpenStack.82 Keystone is a proposed independent authentication service for OpenStack.
83 .83 .
8484
=== removed file 'debian/keystone.config'
--- debian/keystone.config 2012-06-22 12:27:50 +0000
+++ debian/keystone.config 1970-01-01 00:00:00 +0000
@@ -1,19 +0,0 @@
1#!/bin/sh
2set -e
3
4. /usr/share/debconf/confmodule
5
6
7db_input low keystone/configure_db || true
8db_go
9db_get keystone/configure_db
10if [ "$RET" = "true" ]; then
11 if [ -f /usr/share/dbconfig-common/dpkg/config ];
12 then
13 dbc_dbtypes="sqlite3, mysql, pgsql"
14 db_authmethod_user="password"
15 dbc_basepath="/var/lib/keystone"
16 . /usr/share/dbconfig-common/dpkg/config
17 dbc_go keystone $@
18 fi
19fi
200
=== modified file 'debian/keystone.manpages'
--- debian/keystone.manpages 2011-12-16 15:38:05 +0000
+++ debian/keystone.manpages 2013-01-25 16:27:23 +0000
@@ -1,1 +1,1 @@
1debian/man/*1doc/build/man/*
22
=== modified file 'debian/keystone.postinst'
--- debian/keystone.postinst 2012-03-02 09:55:24 +0000
+++ debian/keystone.postinst 2013-01-25 16:27:23 +0000
@@ -2,8 +2,6 @@
22
3set -e3set -e
44
5. /usr/share/debconf/confmodule
6. /usr/share/dbconfig-common/dpkg/postinst
75
8# summary of how this script can be called:6# summary of how this script can be called:
9# * <new-preinst> `install'7# * <new-preinst> `install'
@@ -19,30 +17,10 @@
19 #su -s /bin/sh -c 'exec keystone database sync' keystone17 #su -s /bin/sh -c 'exec keystone database sync' keystone
20 ;;18 ;;
21 configure)19 configure)
22 db_get keystone/configure_db20 if ! grep -q sql_connection /etc/keystone/keystone.conf
23 if [ "$RET" = "true" ]; then21 then
24 dbc_go keystone $@22 su -s /bin/sh -c 'exec keystone-manage db_sync' keystone
25
26 case "$dbc_dbtype" in
27 sqlite3)
28 SQL_CONNECTION="sqlite:///$dbc_basepath/$dbc_dbname.db"
29 ;;
30 mysql)
31 [ -n "$dbc_dbport" ] && dbport=:$dbc_dbport
32 SQL_CONNECTION="mysql://$dbc_dbuser:$dbc_dbpass@${dbc_dbserver:-localhost}$dbport/$dbc_dbname"
33 ;;
34 pgsql)
35 [ -n "$dbc_dbport" ] && dbport=:$dbc_dbport
36 SQL_CONNECTION="pgsql://$dbc_dbuser:$dbc_dbpass@${dbc_dbserver:-localhost}$dbport/$dbc_dbname"
37 ;;
38 *)
39 SQL_CONNECTION="sqlite:////var/lib/keystone/keystone.db"
40 ;;
41 esac
42 [ -z "$2" -o "$dbc_install" = "true" ] \
43 && sed -e "s,_DBC_URL_,$SQL_CONNECTION," -i /etc/keystone/keystone.conf
44 fi23 fi
45 su -s /bin/sh -c 'exec keystone-manage db_sync' keystone
46 ;;24 ;;
47 abort-upgrade)25 abort-upgrade)
48 echo "aport upgrade called"26 echo "aport upgrade called"
4927
=== modified file 'debian/keystone.postrm'
--- debian/keystone.postrm 2012-06-22 12:27:50 +0000
+++ debian/keystone.postrm 2013-01-25 16:27:23 +0000
@@ -2,20 +2,6 @@
22
3set -e3set -e
44
5if [ -f /usr/share/debconf/confmodule ]
6then
7 . /usr/share/debconf/confmodule
8fi
9
10if [ -f /etc/dbconfig-common/keystone.conf ]
11then
12 if [ -f /usr/share/dbconfig-common/dpkg/postrm ]
13 then
14 . /usr/share/dbconfig-common/dpkg/postrm
15 dbc_go keystone $@
16 fi
17fi
18
19case "$1" in5case "$1" in
20 purge)6 purge)
21 rm -rf /var/log/keystone7 rm -rf /var/log/keystone
228
=== removed file 'debian/keystone.prerm'
--- debian/keystone.prerm 2012-06-22 12:27:50 +0000
+++ debian/keystone.prerm 1970-01-01 00:00:00 +0000
@@ -1,17 +0,0 @@
1#!/bin/sh
2
3set -e
4
5. /usr/share/debconf/confmodule
6. /usr/share/dbconfig-common/dpkg/prerm
7
8
9db_get keystone/configure_db
10if [ "$RET" = "true" ]; then
11 # Only cleanup with dbconfig if it was used during
12 # installation (LP: #948719)
13 dbc_go keystone $@
14fi
15
16#DEBHELPER#
17
180
=== modified file 'debian/keystone.templates'
--- debian/keystone.templates 2012-06-22 12:27:50 +0000
+++ debian/keystone.templates 2013-01-25 16:27:23 +0000
@@ -1,7 +1,7 @@
1Template: keystone/configure_db1Template: keystone/configure_db
2Type: boolean2Type: boolean
3Default: false3Default: false
4Description: Set up a database for keystone?4_Description: Set up a database for keystone?
5 No database has been set up for keystone to use. Before continuing,5 No database has been set up for keystone to use. Before continuing,
6 you should make sure you have:6 you should make sure you have:
7 .7 .
88
=== modified file 'debian/keystone.upstart'
--- debian/keystone.upstart 2012-06-22 12:27:50 +0000
+++ debian/keystone.upstart 2013-01-25 16:27:23 +0000
@@ -2,8 +2,10 @@
2author "Soren Hansen <soren@linux2go.dk>"2author "Soren Hansen <soren@linux2go.dk>"
33
4start on (local-filesystems and net-device-up IFACE!=lo)4start on (local-filesystems and net-device-up IFACE!=lo)
5stop on runlevel [016]5stop on runlevel [!2345]
66
7respawn7respawn
88
9exec su -s /bin/sh -c "exec keystone-all" keystone9exec start-stop-daemon --start --chuid keystone \
10 --chdir /var/lib/keystone --name keystone \
11 --exec /usr/bin/keystone-all
1012
=== removed directory 'debian/man'
=== removed file 'debian/man/keystone-admin.8'
--- debian/man/keystone-admin.8 2012-06-22 12:27:50 +0000
+++ debian/man/keystone-admin.8 1970-01-01 00:00:00 +0000
@@ -1,63 +0,0 @@
1.TH keystone 8
2.SH NAME
3keystone-admin \- provides HTTP for administrators.
4.SH SYNOPSIS
5.I [OPTION]...
6.SH DESCRIPTION
7.BR keystone is a Python implementation of the Openstack
8identity service.
9.TP
10.B --version
11show program's version number and exit
12.TP
13.B \-h, --help
14show help messag and exit
15.TP
16.B \-v, --verbose
17Print more verbose output
18.TP
19.B \-d, --debug
20Prrint debugging output to console.
21.TP
22.B \-c PATH, --config-file=PATH
23Path to the config file to use. When not specified (the default),
24we generally look at the first arguement specified to be a config file,
25and if that is also missing, we search standard directories for a config
26file.
27.TP
28.B \-p BIND_PORT, --port=BIND_PORT, --bind-port=BIND_PORT
29Specifies port to listen on.
30.TP
31.B --host=BIND_HOST, --bind-host=BIND_HOST
32Specifies host address to listen on (default is all or 0.0.0.0)
33.TP
34.B \-t, --trace-calls
35Turns on call tracing for troubleshooting
36.TP
37.B \-a PORT, --admin-port=PORT
38Specifies port for Admin API to listen on (default is
3935357)
40.TP
41.B --log-config=PATH
42If this opion is specified, the logging configuration
43file specified is used and overrides any other logging
44options specified. Please see the Python logging
45modules documentation for details on logging
46confgiuration files.
47.TP
48.B --log-date-format=FORMAT
49Format string for %(asctime)s in log records.
50Default: %Y-%m-%d %H:%M:%S
51.TP
52.B --log-file=PATH
53(Optional) Name of log file to output to. If not set,
54logging will go to stdout.
55.TP
56.B --log-didr=LOG_DIR
57(Optional) The directory to keep log files in (will
58be prepended to --logfile)
59
60.SH FILES
61.IR /etc/keystone/keystone.conf
62.SH AUTHOR
63This manual page was written by Chuck Short <zulcss@ubuntu.com>.
640
=== removed file 'debian/man/keystone-auth.8'
--- debian/man/keystone-auth.8 2012-06-22 12:27:50 +0000
+++ debian/man/keystone-auth.8 1970-01-01 00:00:00 +0000
@@ -1,63 +0,0 @@
1.TH keystone 8
2.SH NAME
3keystone-auth \- provides HTTP for users.
4.SH SYNOPSIS
5.I [OPTION]...
6.SH DESCRIPTION
7.BR keystone is a Python implementation of the Openstack
8identity service.
9.TP
10.B --version
11show program's version number and exit
12.TP
13.B \-h, --help
14show help messag and exit
15.TP
16.B \-v, --verbose
17Print more verbose output
18.TP
19.B \-d, --debug
20Prrint debugging output to console.
21.TP
22.B \-c PATH, --config-file=PATH
23Path to the config file to use. When not specified (the default),
24we generally look at the first arguement specified to be a config file,
25and if that is also missing, we search standard directories for a config
26file.
27.TP
28.B \-p BIND_PORT, --port=BIND_PORT, --bind-port=BIND_PORT
29Specifies port to listen on.
30.TP
31.B --host=BIND_HOST, --bind-host=BIND_HOST
32Specifies host address to listen on (default is all or 0.0.0.0)
33.TP
34.B \-t, --trace-calls
35Turns on call tracing for troubleshooting
36.TP
37.B \-a PORT, --admin-port=PORT
38Specifies port for Admin API to listen on (default is
3935357)
40.TP
41.B --log-config=PATH
42If this opion is specified, the logging configuration
43file specified is used and overrides any other logging
44options specified. Please see the Python logging
45modules documentation for details on logging
46confgiuration files.
47.TP
48.B --log-date-format=FORMAT
49Format string for %(asctime)s in log records.
50Default: %Y-%m-%d %H:%M:%S
51.TP
52.B --log-file=PATH
53(Optional) Name of log file to output to. If not set,
54logging will go to stdout.
55.TP
56.B --log-didr=LOG_DIR
57(Optional) The directory to keep log files in (will
58be prepended to --logfile)
59
60.SH FILES
61.IR /etc/keystone/keystone.conf
62.SH AUTHOR
63This manual page was written by Chuck Short <zulcss@ubuntu.com>.
640
=== removed file 'debian/man/keystone-control.8'
--- debian/man/keystone-control.8 2012-06-22 12:27:50 +0000
+++ debian/man/keystone-control.8 1970-01-01 00:00:00 +0000
@@ -1,63 +0,0 @@
1.TH keystone 8
2.SH NAME
3keystone \- Starts/Stops keystone server.
4.SH SYNOPSIS
5.I [OPTION]...
6.SH DESCRIPTION
7.BR keystone is a Python implementation of the Openstack
8identity service.
9.TP
10.B --version
11show program's version number and exit
12.TP
13.B \-h, --help
14show help messag and exit
15.TP
16.B \-v, --verbose
17Print more verbose output
18.TP
19.B \-d, --debug
20Prrint debugging output to console.
21.TP
22.B \-c PATH, --config-file=PATH
23Path to the config file to use. When not specified (the default),
24we generally look at the first arguement specified to be a config file,
25and if that is also missing, we search standard directories for a config
26file.
27.TP
28.B \-p BIND_PORT, --port=BIND_PORT, --bind-port=BIND_PORT
29Specifies port to listen on.
30.TP
31.B --host=BIND_HOST, --bind-host=BIND_HOST
32Specifies host address to listen on (default is all or 0.0.0.0)
33.TP
34.B \-t, --trace-calls
35Turns on call tracing for troubleshooting
36.TP
37.B \-a PORT, --admin-port=PORT
38Specifies port for Admin API to listen on (default is
3935357)
40.TP
41.B --log-config=PATH
42If this opion is specified, the logging configuration
43file specified is used and overrides any other logging
44options specified. Please see the Python logging
45modules documentation for details on logging
46confgiuration files.
47.TP
48.B --log-date-format=FORMAT
49Format string for %(asctime)s in log records.
50Default: %Y-%m-%d %H:%M:%S
51.TP
52.B --log-file=PATH
53(Optional) Name of log file to output to. If not set,
54logging will go to stdout.
55.TP
56.B --log-didr=LOG_DIR
57(Optional) The directory to keep log files in (will
58be prepended to --logfile)
59
60.SH FILES
61.IR /etc/keystone/keystone.conf
62.SH AUTHOR
63This manual page was written by Chuck Short <zulcss@ubuntu.com>.
640
=== removed file 'debian/man/keystone-import.8'
--- debian/man/keystone-import.8 2012-06-22 12:27:50 +0000
+++ debian/man/keystone-import.8 1970-01-01 00:00:00 +0000
@@ -1,12 +0,0 @@
1.TH keystone 8
2.SH NAME
3keystone-import \- import users, tenants, and EC2 credentials from nova.
4.SH SYNOPSIS
5.I [OPTION]...
6.SH DESCRIPTION
7.BR keystone is a Python implementation of the Openstack
8identity service.
9.SH FILES
10.IR /etc/keystone/keystone.conf
11.SH AUTHOR
12This manual page was written by Chuck Short <zulcss@ubuntu.com>.
130
=== removed file 'debian/man/keystone.8'
--- debian/man/keystone.8 2012-06-22 12:27:50 +0000
+++ debian/man/keystone.8 1970-01-01 00:00:00 +0000
@@ -1,64 +0,0 @@
1.TH keystone 8
2.SH NAME
3keystone \- provides HTTP for administrators and users.
4.SH SYNOPSIS
5.I [OPTION]...
6.SH DESCRIPTION
7.B keystone is a Python implementation of the Openstack
8.B identity service. This version has a lack of SSL support.
9.B It should not be run on a trusted network.
10.TP
11.B --version
12show program's version number and exit
13.TP
14.B \-h, --help
15show help messag and exit
16.TP
17.B \-v, --verbose
18Print more verbose output
19.TP
20.B \-d, --debug
21Prrint debugging output to console.
22.TP
23.B \-c PATH, --config-file=PATH
24Path to the config file to use. When not specified (the default),
25we generally look at the first arguement specified to be a config file,
26and if that is also missing, we search standard directories for a config
27file.
28.TP
29.B \-p BIND_PORT, --port=BIND_PORT, --bind-port=BIND_PORT
30Specifies port to listen on.
31.TP
32.B --host=BIND_HOST, --bind-host=BIND_HOST
33Specifies host address to listen on (default is all or 0.0.0.0)
34.TP
35.B \-t, --trace-calls
36Turns on call tracing for troubleshooting
37.TP
38.B \-a PORT, --admin-port=PORT
39Specifies port for Admin API to listen on (default is
4035357)
41.TP
42.B --log-config=PATH
43If this opion is specified, the logging configuration
44file specified is used and overrides any other logging
45options specified. Please see the Python logging
46modules documentation for details on logging
47confgiuration files.
48.TP
49.B --log-date-format=FORMAT
50Format string for %(asctime)s in log records.
51Default: %Y-%m-%d %H:%M:%S
52.TP
53.B --log-file=PATH
54(Optional) Name of log file to output to. If not set,
55logging will go to stdout.
56.TP
57.B --log-didr=LOG_DIR
58(Optional) The directory to keep log files in (will
59be prepended to --logfile)
60
61.SH FILES
62.IR /etc/keystone/keystone.conf
63.SH AUTHOR
64This manual page was written by Chuck Short <zulcss@ubuntu.com>.
650
=== modified file 'debian/patches/fix-ubuntu-tests.patch'
--- debian/patches/fix-ubuntu-tests.patch 2012-11-23 09:01:53 +0000
+++ debian/patches/fix-ubuntu-tests.patch 2013-01-25 16:27:23 +0000
@@ -1,6 +1,16 @@
1diff -Naurp keystone-2013.1.orig/tests/test_keystoneclient.py keystone-2013.1/tests/test_keystoneclient.py1Description: Fix test execution during package build
2--- keystone-2013.1.orig/tests/test_keystoneclient.py 2012-11-22 03:19:01.000000000 -06002 The keystoneclient testsuite includes a number of tests
3+++ keystone-2013.1/tests/test_keystoneclient.py 2012-11-22 10:24:20.729138227 -06003 for older version of keystone which are retrieved from
4 the upstream source repo during testing.
5 .
6 This is not possible during an offline package build so
7 the checkout and tests are disabled/skipped.
8Author: Chuck Short <zulcss@ubuntu.com>
9Author: James Page <james.page@ubuntu.com>
10Forwarded: not-needed
11
12--- a/tests/test_keystoneclient.py
13+++ b/tests/test_keystoneclient.py
4@@ -35,10 +35,6 @@ class CompatTestCase(test.TestCase):14@@ -35,10 +35,6 @@ class CompatTestCase(test.TestCase):
5 def setUp(self):15 def setUp(self):
6 super(CompatTestCase, self).setUp()16 super(CompatTestCase, self).setUp()
@@ -12,3 +22,28 @@
12 self.load_backends()22 self.load_backends()
13 self.load_fixtures(default_fixtures)23 self.load_fixtures(default_fixtures)
14 24
25@@ -1003,6 +999,16 @@ class KcMasterTestCase(CompatTestCase, K
26 client.tenants.list()
27
28
29+def skipped(func):
30+ from nose.plugins.skip import SkipTest
31+
32+ def _():
33+ raise SkipTest("Test %s is skipped" % func.__name__)
34+ _.__name__ = func.__name__
35+ return _
36+
37+
38+@skipped
39 class KcEssex3TestCase(CompatTestCase, KeystoneClientTests):
40 def get_checkout(self):
41 return KEYSTONECLIENT_REPO, 'essex-3'
42@@ -1101,6 +1107,7 @@ class KcEssex3TestCase(CompatTestCase, K
43 raise nose.exc.SkipTest('N/A')
44
45
46+@skipped
47 class Kc11TestCase(CompatTestCase, KeystoneClientTests):
48 def get_checkout(self):
49 return KEYSTONECLIENT_REPO, '0.1.1'
1550
=== added directory 'debian/po'
=== added file 'debian/po/POTFILES.in'
--- debian/po/POTFILES.in 1970-01-01 00:00:00 +0000
+++ debian/po/POTFILES.in 2013-01-25 16:27:23 +0000
@@ -0,0 +1,1 @@
1[type: gettext/rfc822deb] keystone.templates
02
=== added file 'debian/po/templates.pot'
--- debian/po/templates.pot 1970-01-01 00:00:00 +0000
+++ debian/po/templates.pot 2013-01-25 16:27:23 +0000
@@ -0,0 +1,58 @@
1# SOME DESCRIPTIVE TITLE.
2# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3# This file is distributed under the same license as the PACKAGE package.
4# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
5#
6#, fuzzy
7msgid ""
8msgstr ""
9"Project-Id-Version: keystone\n"
10"Report-Msgid-Bugs-To: keystone@packages.debian.org\n"
11"POT-Creation-Date: 2012-11-25 22:21+0000\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"
15"Language: \n"
16"MIME-Version: 1.0\n"
17"Content-Type: text/plain; charset=CHARSET\n"
18"Content-Transfer-Encoding: 8bit\n"
19
20#. Type: boolean
21#. Description
22#: ../keystone.templates:1001
23msgid "Set up a database for keystone?"
24msgstr ""
25
26#. Type: boolean
27#. Description
28#: ../keystone.templates:1001
29msgid ""
30"No database has been set up for keystone to use. Before continuing, you "
31"should make sure you have:"
32msgstr ""
33
34#. Type: boolean
35#. Description
36#: ../keystone.templates:1001
37msgid ""
38" - the server host name (that server must allow TCP connections\n"
39" from this machine);\n"
40" - a username and password to access the database.\n"
41" - A database type that you want to use."
42msgstr ""
43
44#. Type: boolean
45#. Description
46#: ../keystone.templates:1001
47msgid ""
48"If some of these requirements are missing, reject this option and run with "
49"regular sqlite support."
50msgstr ""
51
52#. Type: boolean
53#. Description
54#: ../keystone.templates:1001
55msgid ""
56"Database configuration can be reconfigured later by running 'dpkg-"
57"reconfigure -plow keystone'."
58msgstr ""
059
=== modified file 'debian/rules'
--- debian/rules 2012-11-23 09:01:53 +0000
+++ debian/rules 2013-01-25 16:27:23 +0000
@@ -26,7 +26,7 @@
26 cp tests/test_overrides.conf tests/test_overrides.conf.orig26 cp tests/test_overrides.conf tests/test_overrides.conf.orig
27 cp $(CURDIR)/debian/tests/test_overrides.conf $(CURDIR)/tests/test_overrides.conf27 cp $(CURDIR)/debian/tests/test_overrides.conf $(CURDIR)/tests/test_overrides.conf
28 sed -i 's|%CUR_DIR%|$(CURDIR)|g' $(CURDIR)/tests/test_overrides.conf28 sed -i 's|%CUR_DIR%|$(CURDIR)|g' $(CURDIR)/tests/test_overrides.conf
29 PYTHONPATH=$(CURDIR) bash run_tests.sh -N || true29 PYTHONPATH=$(CURDIR) bash run_tests.sh -N
30 mv $(CURDIR)/tests/test_overrides.conf.orig $(CURDIR)/tests/test_overrides.conf30 mv $(CURDIR)/tests/test_overrides.conf.orig $(CURDIR)/tests/test_overrides.conf
31 rm -rf $(CURDIR)/debian/tests/testing.db $(CURDIR)/debian/tests/keystone-signing31 rm -rf $(CURDIR)/debian/tests/testing.db $(CURDIR)/debian/tests/keystone-signing
32endif32endif
3333
=== modified file 'debian/tests/test_overrides.conf'
--- debian/tests/test_overrides.conf 2012-11-02 13:48:49 +0000
+++ debian/tests/test_overrides.conf 2013-01-25 16:27:23 +0000
@@ -13,6 +13,6 @@
13idle_timeout = 20013idle_timeout = 200
1414
15[signing]15[signing]
16certfile = signing/signing_cert.pem16certfile = ../examples/pki/certs/signing_cert.pem
17keyfile = signing/private_key.pem17keyfile = ../examples/pki/private/signing_key.pem
18ca_certs = signing/cacert.pem18ca_certs = ../examples/pki/certs/cacert.pem
1919
=== modified file 'doc/source/configuration.rst'
--- doc/source/configuration.rst 2012-11-23 09:01:53 +0000
+++ doc/source/configuration.rst 2013-01-25 16:27:23 +0000
@@ -388,10 +388,10 @@
388* ``etc/logging.conf.sample``388* ``etc/logging.conf.sample``
389* ``etc/default_catalog.templates``389* ``etc/default_catalog.templates``
390390
391.. _`prepare your Essex deployment`:391.. _`prepare your deployment`:
392392
393Preparing your Essex deployment393Preparing your deployment
394===============================394=========================
395395
396Step 1: Configure keystone.conf396Step 1: Configure keystone.conf
397-------------------------------397-------------------------------
@@ -450,9 +450,9 @@
450.. NOTE::450.. NOTE::
451451
452 Before you can import your legacy data, you must first452 Before you can import your legacy data, you must first
453 `prepare your Essex deployment`_.453 `prepare your deployment`_.
454454
455Step 1: Ensure your Essex deployment can access your legacy database455Step 1: Ensure your deployment can access your legacy database
456--------------------------------------------------------------------456--------------------------------------------------------------------
457457
458Your legacy ``keystone.conf`` contains a SQL configuration section called458Your legacy ``keystone.conf`` contains a SQL configuration section called
@@ -461,7 +461,7 @@
461461
462 sql_connection = sqlite:///keystone.db462 sql_connection = sqlite:///keystone.db
463463
464This connection string needs to be accessible from your Essex deployment (e.g.464This connection string needs to be accessible from your deployment (e.g.
465you may need to copy your SQLite ``*.db`` file to a new server, adjust the465you may need to copy your SQLite ``*.db`` file to a new server, adjust the
466relative path as appropriate, or open a firewall for MySQL, etc).466relative path as appropriate, or open a firewall for MySQL, etc).
467467
@@ -474,7 +474,7 @@
474 $ keystone-manage import_legacy <sql_connection>474 $ keystone-manage import_legacy <sql_connection>
475475
476You should now be able to run the same command you used to test your new476You should now be able to run the same command you used to test your new
477database above, but now you'll see your legacy Keystone data in Essex::477database above, but now you'll see your legacy Keystone data::
478478
479 $ keystone --token ADMIN --endpoint http://127.0.0.1:35357/v2.0/ tenant-list479 $ keystone --token ADMIN --endpoint http://127.0.0.1:35357/v2.0/ tenant-list
480 +----------------------------------+----------------+---------+480 +----------------------------------+----------------+---------+
@@ -491,7 +491,7 @@
491===============================================================491===============================================================
492492
493While legacy Keystone deployments stored the service catalog in the database,493While legacy Keystone deployments stored the service catalog in the database,
494the service catalog in Essex is stored in a flat ``template_file``. An example494the service catalog is stored in a flat ``template_file``. An example
495service catalog template file may be found in495service catalog template file may be found in
496``etc/default_catalog.templates``. You can change the path to your service496``etc/default_catalog.templates``. You can change the path to your service
497catalog template in ``keystone.conf`` by changing the value of497catalog template in ``keystone.conf`` by changing the value of
@@ -510,13 +510,13 @@
510========================510========================
511511
512Migration of users, projects (aka tenants), roles and EC2 credentials512Migration of users, projects (aka tenants), roles and EC2 credentials
513is supported for the Essex release of Nova. To migrate your auth513is supported for the Essex and later releases of Nova. To migrate your auth
514data from Nova, use the following steps:514data from Nova, use the following steps:
515515
516.. NOTE::516.. NOTE::
517517
518 Before you can migrate from nova auth, you must first518 Before you can migrate from nova auth, you must first
519 `prepare your Essex deployment`_.519 `prepare your deployment`_.
520520
521Step 1: Export your data from Nova521Step 1: Export your data from Nova
522----------------------------------522----------------------------------
523523
=== modified file 'doc/source/configuringservices.rst'
--- doc/source/configuringservices.rst 2012-09-07 13:04:01 +0000
+++ doc/source/configuringservices.rst 2013-01-25 16:27:23 +0000
@@ -176,151 +176,8 @@
176---------------------------------176---------------------------------
177177
178Similar to Nova, swift can be configured to use Keystone for authentication178Similar to Nova, swift can be configured to use Keystone for authentication
179rather than its built in 'tempauth'.179rather than its built in 'tempauth'. Refer to the `overview_auth` documentation
180180in Swift.
1811. Add a service endpoint for Swift to Keystone
182
1832. Configure the paste file for swift-proxy (`/etc/swift/swift-proxy.conf`)
184
1853. Reconfigure Swift's proxy server to use Keystone instead of TempAuth.
186 Here's an example `/etc/swift/proxy-server.conf`::
187
188 [DEFAULT]
189 bind_port = 8888
190 user = <user>
191
192 [pipeline:main]
193 pipeline = catch_errors healthcheck cache authtoken keystone proxy-server
194
195 [app:proxy-server]
196 use = egg:swift#proxy
197 account_autocreate = true
198
199 [filter:keystone]
200 paste.filter_factory = keystone.middleware.swift_auth:filter_factory
201 operator_roles = admin, swiftoperator
202
203 [filter:authtoken]
204 paste.filter_factory = keystone.middleware.auth_token:filter_factory
205 # Delaying the auth decision is required to support token-less
206 # usage for anonymous referrers ('.r:*') or for tempurl/formpost
207 # middleware.
208 delay_auth_decision = 1
209 auth_port = 35357
210 auth_host = 127.0.0.1
211 auth_token = ADMIN
212 admin_token = ADMIN
213
214 [filter:cache]
215 use = egg:swift#memcache
216 set log_name = cache
217
218 [filter:catch_errors]
219 use = egg:swift#catch_errors
220
221 [filter:healthcheck]
222 use = egg:swift#healthcheck
223
224.. Note::
225 Your user needs to have the role swiftoperator or admin by default
226 to be able to operate on an swift account or as specified by the
227 variable `operator_roles`.
228
2294. Restart swift
230
2315. Verify that keystone is providing authentication to Swift
232
233 $ swift -V 2 -A http://localhost:5000/v2.0 -U admin:admin -K ADMIN stat
234
235.. NOTE::
236 Instead of connecting to Swift here, as you would with other services, we
237 are connecting directly to Keystone.
238
239Configuring Swift with S3 emulation to use Keystone
240---------------------------------------------------
241
242Keystone supports validating S3 tokens using the same tokens as the
243generated EC2 tokens. When you have generated a pair of EC2 access
244token and secret you can access your swift cluster directly with the
245S3 API.
246
2471. Ensure you have defined the S3 service in your `keystone.conf`. First, define the filter as follows::
248
249 [filter:s3_extension]
250 paste.filter_factory = keystone.contrib.s3:S3Extension.factory
251
252Then, ensure that the filter is being called by the admin_api pipeline, as follows::
253
254 [pipeline:admin_api]
255 pipeline = token_auth [....] ec2_extension s3_extension [...]
256
2572. Configure the paste file for swift-proxy
258 (`/etc/swift/swift-proxy.conf` to use S3token and Swift3
259 middleware.
260
261 Here's an example that by default communicates with keystone via https ::
262
263 [DEFAULT]
264 bind_port = 8080
265 user = <user>
266
267 [pipeline:main]
268 pipeline = catch_errors healthcheck cache swift3 s3token authtoken keystone proxy-server
269
270 [app:proxy-server]
271 use = egg:swift#proxy
272 account_autocreate = true
273
274 [filter:catch_errors]
275 use = egg:swift#catch_errors
276
277 [filter:healthcheck]
278 use = egg:swift#healthcheck
279
280 [filter:cache]
281 use = egg:swift#memcache
282
283 [filter:swift3]
284 use = egg:swift#swift3
285
286 [filter:keystone]
287 paste.filter_factory = keystone.middleware.swift_auth:filter_factory
288 operator_roles = admin, swiftoperator
289
290 [filter:s3token]
291 paste.filter_factory = keystone.middleware.s3_token:filter_factory
292 # uncomment the following line if you don't want to use SSL
293 # auth_protocol = http
294 auth_port = 35357
295 auth_host = 127.0.0.1
296
297 [filter:authtoken]
298 paste.filter_factory = keystone.middleware.auth_token:filter_factory
299 # uncomment the following line if you don't want to use SSL
300 # auth_protocol = http
301 auth_port = 35357
302 auth_host = 127.0.0.1
303 auth_token = ADMIN
304 admin_token = ADMIN
305
3063. You can then access directly your Swift via the S3 API, here's an
307 example with the `boto` library::
308
309 import boto
310 import boto.s3.connection
311
312 connection = boto.connect_s3(
313 aws_access_key_id='<ec2 access key for user>',
314 aws_secret_access_key='<ec2 secret access key for user>',
315 port=8080,
316 host='localhost',
317 is_secure=False,
318 calling_format=boto.s3.connection.OrdinaryCallingFormat())
319
320
321.. Note::
322 With the S3 middleware you are connecting to the `Swift` proxy and
323 not to `keystone`.
324181
325Auth-Token Middleware with Username and Password182Auth-Token Middleware with Username and Password
326------------------------------------------------183------------------------------------------------
327184
=== added file 'doc/source/external-auth.rst'
--- doc/source/external-auth.rst 1970-01-01 00:00:00 +0000
+++ doc/source/external-auth.rst 2013-01-25 16:27:23 +0000
@@ -0,0 +1,117 @@
1===========================================
2Using external authentication with Keystone
3===========================================
4
5When Keystone is executed in :doc:`HTTPD <apache-httpd>` it is possible to
6use external authentication methods different from the authentication
7provided by the identity store backend. For example, this makes possible to
8use a SQL identity backend together with X.509 authentication, Kerberos, etc.
9instead of using the username/password combination.
10
11Using HTTPD authentication
12==========================
13
14Webservers like Apache HTTP support many methods of authentication. Keystone can
15profit from this feature and let the authentication be done in the webserver,
16that will pass down the authenticated user to Keystone using the ``REMOTE_USER``
17environment variable. This user must exist in advance in the identity backend
18so as to get a token from the controller.
19
20To use this method, Keystone should be running on :doc:`HTTPD <apache-httpd>`.
21
22X.509 example
23-------------
24
25The following snippet for the Apache conf will authenticate the user based on
26a valid X.509 certificate from a known CA::
27
28 <VirtualHost _default_:5000>
29 SSLEngine on
30 SSLCertificateFile /etc/ssl/certs/ssl.cert
31 SSLCertificateKeyFile /etc/ssl/private/ssl.key
32
33 SSLCACertificatePath /etc/ssl/allowed_cas
34 SSLCARevocationPath /etc/ssl/allowed_cas
35 SSLUserName SSL_CLIENT_S_DN_CN
36 SSLVerifyClient require
37 SSLVerifyDepth 10
38
39 (...)
40 </VirtualHost>
41
42Developing a WSGI middleware for authentication
43===============================================
44
45In addition to the method described above, it is possible to implement other
46custom authentication mechanisms using the ``REMOTE_USER`` WSGI environment
47variable.
48
49.. ATTENTION::
50 Please note that even if it is possible to develop a custom authentication
51 module, it is preferable to use the modules in the HTTPD server. Such
52 authentication modules in webservers like Apache have normally undergone
53 years of development and use in production systems and are actively maintained
54 upstream. Developing a custom authentication module that implements the same
55 authentication as an existing Apache module likely introduces a higher
56 security risk.
57
58If you find you must implement a custom authentication mechanism, you will need
59to develop a custom WSGI middleware pipeline component. This middleware should
60set the environment variable ``REMOTE_USER`` to the authenticated username.
61Keystone then will assume that the user has been already authenticated upstream
62and will not try to authenticate it. However, as with HTTPD authentication, the
63user must exist in advance in the identity backend so that a proper token can
64be issued.
65
66Your code should set the ``REMOTE_USER`` if the user is properly authenticated,
67following the semantics below::
68
69 class MyMiddlewareAuth(wsgi.Middleware):
70 def __init__(self, *args, **kwargs):
71 super(MyMiddlewareAuth, self).__init__(*args, **kwargs)
72
73 def process_request(self, request):
74 if request.environ.get('REMOTE_USER', None) is not None:
75 # Assume that it is authenticated upstream
76 return self.application
77
78 if not self.is_auth_applicable(request):
79 # Not applicable
80 return self.application
81
82 username = self.do_auth(request):
83 if username is not None:
84 # User is authenticated
85 request.environ['REMOTE_USER'] = username
86 else:
87 # User is not authenticated
88 raise exception.Unauthorized("Invalid user")
89
90
91Pipeline configuration
92----------------------
93
94Once you have your WSGI middleware component developed you have to add it to
95your pipeline. The first step is to add the middleware to your configuration file.
96Assuming that your middleware module is ``keystone.middleware.MyMiddlewareAuth``,
97you can configure it in your ``keystone.conf`` as::
98
99 [filter:my_auth]
100 paste.filter_factory = keystone.middleware.MyMiddlewareAuth.factory
101
102The second step is to add your middleware to the pipeline. The exact place where
103you should place it will depend on your code (i.e. if you need for example that
104the request body is converted from JSON before perform the authentication you
105should place it after the ``json_body`` filter) but it should be set before the
106``public_service`` (for the ``public_api`` pipeline) or ``admin_service`` (for
107the ``admin_api`` pipeline), since they consume authentication.
108
109For example, if the original pipeline looks like this::
110
111 [pipeline:public_api]
112 pipeline = stats_monitoring url_normalize token_auth admin_token_auth xml_body json_body debug ec2_extension user_crud_extension public_service
113
114Your modified pipeline might then look like this::
115
116 [pipeline:public_api]
117 pipeline = stats_monitoring url_normalize token_auth admin_token_auth xml_body json_body my_auth debug ec2_extension user_crud_extension public_service
0118
=== modified file 'doc/source/index.rst'
--- doc/source/index.rst 2012-11-23 09:01:53 +0000
+++ doc/source/index.rst 2013-01-25 16:27:23 +0000
@@ -66,6 +66,7 @@
66 middlewarearchitecture66 middlewarearchitecture
67 api_curl_examples67 api_curl_examples
68 apache-httpd68 apache-httpd
69 external-auth
6970
70Code Documentation71Code Documentation
71==================72==================
7273
=== modified file 'doc/source/setup.rst'
--- doc/source/setup.rst 2012-03-16 11:19:40 +0000
+++ doc/source/setup.rst 2013-01-25 16:27:23 +0000
@@ -70,7 +70,7 @@
7070
71The first is the list of dependencies needed for running keystone, the second list includes dependencies used for active development and testing of keystone itself.71The first is the list of dependencies needed for running keystone, the second list includes dependencies used for active development and testing of keystone itself.
7272
73These depdendencies can be installed from PyPi_ using the python tool pip_.73These dependencies can be installed from PyPi_ using the python tool pip_.
7474
75.. _PyPi: http://pypi.python.org/75.. _PyPi: http://pypi.python.org/
76.. _pip: http://pypi.python.org/pypi/pip76.. _pip: http://pypi.python.org/pypi/pip
7777
=== modified file 'keystone.egg-info/SOURCES.txt'
--- keystone.egg-info/SOURCES.txt 2012-11-23 09:01:53 +0000
+++ keystone.egg-info/SOURCES.txt 2013-01-25 16:27:23 +0000
@@ -26,6 +26,7 @@
26doc/source/configuration.rst26doc/source/configuration.rst
27doc/source/configuringservices.rst27doc/source/configuringservices.rst
28doc/source/developing.rst28doc/source/developing.rst
29doc/source/external-auth.rst
29doc/source/index.rst30doc/source/index.rst
30doc/source/installing.rst31doc/source/installing.rst
31doc/source/middlewarearchitecture.rst32doc/source/middlewarearchitecture.rst
@@ -81,7 +82,9 @@
81keystone/clean.py82keystone/clean.py
82keystone/cli.py83keystone/cli.py
83keystone/config.py84keystone/config.py
85keystone/controllers.py
84keystone/exception.py86keystone/exception.py
87keystone/routers.py
85keystone/service.py88keystone/service.py
86keystone/test.py89keystone/test.py
87keystone.egg-info/PKG-INFO90keystone.egg-info/PKG-INFO
@@ -91,7 +94,9 @@
91keystone.egg-info/requires.txt94keystone.egg-info/requires.txt
92keystone.egg-info/top_level.txt95keystone.egg-info/top_level.txt
93keystone/catalog/__init__.py96keystone/catalog/__init__.py
97keystone/catalog/controllers.py
94keystone/catalog/core.py98keystone/catalog/core.py
99keystone/catalog/routers.py
95keystone/catalog/backends/__init__.py100keystone/catalog/backends/__init__.py
96keystone/catalog/backends/kvs.py101keystone/catalog/backends/kvs.py
97keystone/catalog/backends/sql.py102keystone/catalog/backends/sql.py
@@ -100,12 +105,14 @@
100keystone/common/bufferedhttp.py105keystone/common/bufferedhttp.py
101keystone/common/cms.py106keystone/common/cms.py
102keystone/common/controller.py107keystone/common/controller.py
108keystone/common/dependency.py
103keystone/common/kvs.py109keystone/common/kvs.py
104keystone/common/logging.py110keystone/common/logging.py
105keystone/common/manager.py111keystone/common/manager.py
106keystone/common/models.py112keystone/common/models.py
107keystone/common/openssl.py113keystone/common/openssl.py
108keystone/common/policy.py114keystone/common/policy.py
115keystone/common/router.py
109keystone/common/serializer.py116keystone/common/serializer.py
110keystone/common/systemd.py117keystone/common/systemd.py
111keystone/common/utils.py118keystone/common/utils.py
@@ -127,13 +134,19 @@
127keystone/common/sql/migrate_repo/versions/002_sqlite_downgrade.sql134keystone/common/sql/migrate_repo/versions/002_sqlite_downgrade.sql
128keystone/common/sql/migrate_repo/versions/002_sqlite_upgrade.sql135keystone/common/sql/migrate_repo/versions/002_sqlite_upgrade.sql
129keystone/common/sql/migrate_repo/versions/002_token_id_hash.py136keystone/common/sql/migrate_repo/versions/002_token_id_hash.py
130keystone/common/sql/migrate_repo/versions/003_sqlite_downgrade.sql
131keystone/common/sql/migrate_repo/versions/003_sqlite_upgrade.sql137keystone/common/sql/migrate_repo/versions/003_sqlite_upgrade.sql
132keystone/common/sql/migrate_repo/versions/003_token_valid.py138keystone/common/sql/migrate_repo/versions/003_token_valid.py
133keystone/common/sql/migrate_repo/versions/004_undo_token_id_hash.py139keystone/common/sql/migrate_repo/versions/004_undo_token_id_hash.py
134keystone/common/sql/migrate_repo/versions/005_set_utf8_character_set.py140keystone/common/sql/migrate_repo/versions/005_set_utf8_character_set.py
135keystone/common/sql/migrate_repo/versions/006_add_policy_table.py141keystone/common/sql/migrate_repo/versions/006_add_policy_table.py
136keystone/common/sql/migrate_repo/versions/007_add_domain_tables.py142keystone/common/sql/migrate_repo/versions/007_add_domain_tables.py
143keystone/common/sql/migrate_repo/versions/008_normalize_identity.py
144keystone/common/sql/migrate_repo/versions/008_sqlite_downgrade.sql
145keystone/common/sql/migrate_repo/versions/009_normalize_identity_migration.py
146keystone/common/sql/migrate_repo/versions/010_endpoints_v3.py
147keystone/common/sql/migrate_repo/versions/011_populate_endpoint_type.py
148keystone/common/sql/migrate_repo/versions/012_drop_legacy_endpoints.py
149keystone/common/sql/migrate_repo/versions/013_add_group_tables.py
137keystone/common/sql/migrate_repo/versions/__init__.py150keystone/common/sql/migrate_repo/versions/__init__.py
138keystone/contrib/__init__.py151keystone/contrib/__init__.py
139keystone/contrib/admin_crud/__init__.py152keystone/contrib/admin_crud/__init__.py
@@ -152,7 +165,9 @@
152keystone/contrib/user_crud/__init__.py165keystone/contrib/user_crud/__init__.py
153keystone/contrib/user_crud/core.py166keystone/contrib/user_crud/core.py
154keystone/identity/__init__.py167keystone/identity/__init__.py
168keystone/identity/controllers.py
155keystone/identity/core.py169keystone/identity/core.py
170keystone/identity/routers.py
156keystone/identity/backends/__init__.py171keystone/identity/backends/__init__.py
157keystone/identity/backends/kvs.py172keystone/identity/backends/kvs.py
158keystone/identity/backends/pam.py173keystone/identity/backends/pam.py
@@ -161,13 +176,13 @@
161keystone/identity/backends/ldap/core.py176keystone/identity/backends/ldap/core.py
162keystone/locale/keystone.pot177keystone/locale/keystone.pot
163keystone/locale/ca/LC_MESSAGES/keystone.po178keystone/locale/ca/LC_MESSAGES/keystone.po
179keystone/locale/hu/LC_MESSAGES/keystone.po
164keystone/locale/ja/LC_MESSAGES/keystone.po180keystone/locale/ja/LC_MESSAGES/keystone.po
165keystone/middleware/__init__.py181keystone/middleware/__init__.py
166keystone/middleware/auth_token.py182keystone/middleware/auth_token.py
167keystone/middleware/core.py183keystone/middleware/core.py
168keystone/middleware/ec2_token.py184keystone/middleware/ec2_token.py
169keystone/middleware/s3_token.py185keystone/middleware/s3_token.py
170keystone/middleware/swift_auth.py
171keystone/openstack/__init__.py186keystone/openstack/__init__.py
172keystone/openstack/common/README187keystone/openstack/common/README
173keystone/openstack/common/__init__.py188keystone/openstack/common/__init__.py
@@ -178,12 +193,16 @@
178keystone/openstack/common/setup.py193keystone/openstack/common/setup.py
179keystone/openstack/common/timeutils.py194keystone/openstack/common/timeutils.py
180keystone/policy/__init__.py195keystone/policy/__init__.py
196keystone/policy/controllers.py
181keystone/policy/core.py197keystone/policy/core.py
198keystone/policy/routers.py
182keystone/policy/backends/__init__.py199keystone/policy/backends/__init__.py
183keystone/policy/backends/rules.py200keystone/policy/backends/rules.py
184keystone/policy/backends/sql.py201keystone/policy/backends/sql.py
185keystone/token/__init__.py202keystone/token/__init__.py
203keystone/token/controllers.py
186keystone/token/core.py204keystone/token/core.py
205keystone/token/routers.py
187keystone/token/backends/__init__.py206keystone/token/backends/__init__.py
188keystone/token/backends/kvs.py207keystone/token/backends/kvs.py
189keystone/token/backends/memcache.py208keystone/token/backends/memcache.py
@@ -203,6 +222,7 @@
203tests/legacy_essex.mysql222tests/legacy_essex.mysql
204tests/legacy_essex.sqlite223tests/legacy_essex.sqlite
205tests/policy.json224tests/policy.json
225tests/test_auth.py
206tests/test_auth_token_middleware.py226tests/test_auth_token_middleware.py
207tests/test_backend.py227tests/test_backend.py
208tests/test_backend_kvs.py228tests/test_backend_kvs.py
@@ -213,8 +233,11 @@
213tests/test_backend_templated.py233tests/test_backend_templated.py
214tests/test_cert_setup.py234tests/test_cert_setup.py
215tests/test_content_types.py235tests/test_content_types.py
236tests/test_contrib_s3_core.py
237tests/test_drivers.py
216tests/test_exception.py238tests/test_exception.py
217tests/test_import_legacy.py239tests/test_import_legacy.py
240tests/test_injection.py
218tests/test_keystoneclient.py241tests/test_keystoneclient.py
219tests/test_keystoneclient_sql.py242tests/test_keystoneclient_sql.py
220tests/test_middleware.py243tests/test_middleware.py
@@ -223,12 +246,10 @@
223tests/test_policy.py246tests/test_policy.py
224tests/test_s3_token_middleware.py247tests/test_s3_token_middleware.py
225tests/test_serializer.py248tests/test_serializer.py
226tests/test_service.py
227tests/test_setup.py249tests/test_setup.py
228tests/test_singular_plural.py250tests/test_singular_plural.py
229tests/test_sql_upgrade.py251tests/test_sql_upgrade.py
230tests/test_ssl.py252tests/test_ssl.py
231tests/test_swift_auth_middleware.py
232tests/test_url_middleware.py253tests/test_url_middleware.py
233tests/test_utils.py254tests/test_utils.py
234tests/test_v3.py255tests/test_v3.py
@@ -238,6 +259,7 @@
238tests/test_versions.py259tests/test_versions.py
239tests/test_wsgi.py260tests/test_wsgi.py
240tools/convert_to_sqlite.sh261tools/convert_to_sqlite.sh
262tools/flakes.py
241tools/install_venv.py263tools/install_venv.py
242tools/pip-requires264tools/pip-requires
243tools/sample_data.sh265tools/sample_data.sh
244266
=== modified file 'keystone.egg-info/requires.txt'
--- keystone.egg-info/requires.txt 2012-11-23 09:01:53 +0000
+++ keystone.egg-info/requires.txt 2013-01-25 16:27:23 +0000
@@ -1,5 +1,5 @@
1pam==0.1.41pam==0.1.4
2WebOb==1.0.82WebOb==1.2.3
3eventlet3eventlet
4greenlet4greenlet
5PasteDeploy5PasteDeploy
66
=== modified file 'keystone/catalog/__init__.py'
--- keystone/catalog/__init__.py 2012-03-16 11:19:40 +0000
+++ keystone/catalog/__init__.py 2013-01-25 16:27:23 +0000
@@ -15,3 +15,5 @@
15# under the License.15# under the License.
1616
17from keystone.catalog.core import *17from keystone.catalog.core import *
18from keystone.catalog import controllers
19from keystone.catalog import routers
1820
=== modified file 'keystone/catalog/backends/sql.py'
--- keystone/catalog/backends/sql.py 2012-11-23 09:01:53 +0000
+++ keystone/catalog/backends/sql.py 2013-01-25 16:27:23 +0000
@@ -36,12 +36,14 @@
3636
37class Endpoint(sql.ModelBase, sql.DictBase):37class Endpoint(sql.ModelBase, sql.DictBase):
38 __tablename__ = 'endpoint'38 __tablename__ = 'endpoint'
39 attributes = ['id', 'region', 'service_id']39 attributes = ['id', 'interface', 'region', 'service_id', 'url']
40 id = sql.Column(sql.String(64), primary_key=True)40 id = sql.Column(sql.String(64), primary_key=True)
41 interface = sql.Column(sql.String(8), primary_key=True)
41 region = sql.Column('region', sql.String(255))42 region = sql.Column('region', sql.String(255))
42 service_id = sql.Column(sql.String(64),43 service_id = sql.Column(sql.String(64),
43 sql.ForeignKey('service.id'),44 sql.ForeignKey('service.id'),
44 nullable=False)45 nullable=False)
46 url = sql.Column(sql.Text())
45 extra = sql.Column(sql.JsonBlob())47 extra = sql.Column(sql.JsonBlob())
4648
4749
@@ -88,7 +90,9 @@
88 old_dict = ref.to_dict()90 old_dict = ref.to_dict()
89 old_dict.update(service_ref)91 old_dict.update(service_ref)
90 new_service = Service.from_dict(old_dict)92 new_service = Service.from_dict(old_dict)
91 ref.type = new_service.type93 for attr in Service.attributes:
94 if attr != 'id':
95 setattr(ref, attr, getattr(new_service, attr))
92 ref.extra = new_service.extra96 ref.extra = new_service.extra
93 session.flush()97 session.flush()
94 return ref.to_dict()98 return ref.to_dict()
@@ -132,8 +136,9 @@
132 old_dict = ref.to_dict()136 old_dict = ref.to_dict()
133 old_dict.update(endpoint_ref)137 old_dict.update(endpoint_ref)
134 new_endpoint = Endpoint.from_dict(old_dict)138 new_endpoint = Endpoint.from_dict(old_dict)
135 ref.service_id = new_endpoint.service_id139 for attr in Endpoint.attributes:
136 ref.region = new_endpoint.region140 if attr != 'id':
141 setattr(ref, attr, getattr(new_endpoint, attr))
137 ref.extra = new_endpoint.extra142 ref.extra = new_endpoint.extra
138 session.flush()143 session.flush()
139 return ref.to_dict()144 return ref.to_dict()
@@ -142,25 +147,28 @@
142 d = dict(CONF.iteritems())147 d = dict(CONF.iteritems())
143 d.update({'tenant_id': tenant_id,148 d.update({'tenant_id': tenant_id,
144 'user_id': user_id})149 'user_id': user_id})
150
145 catalog = {}151 catalog = {}
146152 services = {}
147 endpoints = self.list_endpoints()153 for endpoint in self.list_endpoints():
148 for ep in endpoints:154 # look up the service
149 service = self.get_service(ep['service_id'])155 services.setdefault(
150 srv_type = service['type']156 endpoint['service_id'],
151 srv_name = service['name']157 self.get_service(endpoint['service_id']))
152 region = ep['region']158 service = services[endpoint['service_id']]
153159
154 if region not in catalog:160 # add the endpoint to the catalog if it's not already there
155 catalog[region] = {}161 catalog.setdefault(endpoint['region'], {})
156162 catalog[endpoint['region']].setdefault(
157 catalog[region][srv_type] = {}163 service['type'], {
158164 'id': endpoint['id'],
159 srv_type = catalog[region][srv_type]165 'name': service['name'],
160 srv_type['id'] = ep['id']166 'publicURL': '', # this may be overridden, but must exist
161 srv_type['name'] = srv_name167 })
162 srv_type['publicURL'] = core.format_url(ep.get('publicurl', ''), d)168
163 srv_type['internalURL'] = core.format_url(ep.get('internalurl'), d)169 # add the interface's url
164 srv_type['adminURL'] = core.format_url(ep.get('adminurl'), d)170 url = core.format_url(endpoint.get('url'), d)
171 interface_url = '%sURL' % endpoint['interface']
172 catalog[endpoint['region']][service['type']][interface_url] = url
165173
166 return catalog174 return catalog
167175
=== modified file 'keystone/catalog/backends/templated.py'
--- keystone/catalog/backends/templated.py 2012-11-02 13:48:49 +0000
+++ keystone/catalog/backends/templated.py 2013-01-25 16:27:23 +0000
@@ -106,7 +106,7 @@
106 try:106 try:
107 self.templates = parse_templates(open(template_file))107 self.templates = parse_templates(open(template_file))
108 except IOError:108 except IOError:
109 LOG.critical('Unable to open template file %s' % template_file)109 LOG.critical(_('Unable to open template file %s') % template_file)
110 raise110 raise
111111
112 def get_catalog(self, user_id, tenant_id, metadata=None):112 def get_catalog(self, user_id, tenant_id, metadata=None):
113113
=== added file 'keystone/catalog/controllers.py'
--- keystone/catalog/controllers.py 1970-01-01 00:00:00 +0000
+++ keystone/catalog/controllers.py 2013-01-25 16:27:23 +0000
@@ -0,0 +1,184 @@
1# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Copyright 2012 OpenStack LLC
4# Copyright 2012 Canonical Ltd.
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17
18import uuid
19
20from keystone.common import controller
21from keystone.common import dependency
22from keystone import exception
23
24
25INTERFACES = ['public', 'internal', 'admin']
26
27
28@dependency.requires('catalog_api')
29class Service(controller.V2Controller):
30 def get_services(self, context):
31 self.assert_admin(context)
32 service_list = self.catalog_api.list_services(context)
33 return {'OS-KSADM:services': service_list}
34
35 def get_service(self, context, service_id):
36 self.assert_admin(context)
37 service_ref = self.catalog_api.get_service(context, service_id)
38 return {'OS-KSADM:service': service_ref}
39
40 def delete_service(self, context, service_id):
41 self.assert_admin(context)
42 self.catalog_api.delete_service(context, service_id)
43
44 def create_service(self, context, OS_KSADM_service):
45 self.assert_admin(context)
46 service_id = uuid.uuid4().hex
47 service_ref = OS_KSADM_service.copy()
48 service_ref['id'] = service_id
49 new_service_ref = self.catalog_api.create_service(
50 context, service_id, service_ref)
51 return {'OS-KSADM:service': new_service_ref}
52
53
54@dependency.requires('catalog_api')
55class Endpoint(controller.V2Controller):
56 def get_endpoints(self, context):
57 """Merge matching v3 endpoint refs into legacy refs."""
58 self.assert_admin(context)
59 legacy_endpoints = {}
60 for endpoint in self.catalog_api.list_endpoints(context):
61 if not endpoint['legacy_endpoint_id']:
62 # endpoints created in v3 should not appear on the v2 API
63 continue
64
65 # is this is a legacy endpoint we haven't indexed yet?
66 if endpoint['legacy_endpoint_id'] not in legacy_endpoints:
67 legacy_ep = endpoint.copy()
68 legacy_ep['id'] = legacy_ep.pop('legacy_endpoint_id')
69 legacy_ep.pop('interface')
70 legacy_ep.pop('url')
71
72 legacy_endpoints[endpoint['legacy_endpoint_id']] = legacy_ep
73 else:
74 legacy_ep = legacy_endpoints[endpoint['legacy_endpoint_id']]
75
76 # add the legacy endpoint with an interface url
77 legacy_ep['%surl' % endpoint['interface']] = endpoint['url']
78 return {'endpoints': legacy_endpoints.values()}
79
80 def create_endpoint(self, context, endpoint):
81 """Create three v3 endpoint refs based on a legacy ref."""
82 self.assert_admin(context)
83
84 legacy_endpoint_ref = endpoint.copy()
85
86 urls = dict((i, endpoint.pop('%surl' % i)) for i in INTERFACES)
87 legacy_endpoint_id = uuid.uuid4().hex
88 for interface, url in urls.iteritems():
89 endpoint_ref = endpoint.copy()
90 endpoint_ref['id'] = uuid.uuid4().hex
91 endpoint_ref['legacy_endpoint_id'] = legacy_endpoint_id
92 endpoint_ref['interface'] = interface
93 endpoint_ref['url'] = url
94
95 self.catalog_api.create_endpoint(
96 context, endpoint_ref['id'], endpoint_ref)
97
98 legacy_endpoint_ref['id'] = legacy_endpoint_id
99 return {'endpoint': legacy_endpoint_ref}
100
101 def delete_endpoint(self, context, endpoint_id):
102 """Delete up to three v3 endpoint refs based on a legacy ref ID."""
103 self.assert_admin(context)
104
105 deleted_at_least_one = False
106 for endpoint in self.catalog_api.list_endpoints(context):
107 if endpoint['legacy_endpoint_id'] == endpoint_id:
108 self.catalog_api.delete_endpoint(context, endpoint['id'])
109 deleted_at_least_one = True
110
111 if not deleted_at_least_one:
112 raise exception.EndpointNotFound(endpoint_id=endpoint_id)
113
114
115@dependency.requires('catalog_api')
116class ServiceV3(controller.V3Controller):
117 @controller.protected
118 def create_service(self, context, service):
119 ref = self._assign_unique_id(self._normalize_dict(service))
120 self._require_attribute(ref, 'type')
121
122 ref = self.catalog_api.create_service(context, ref['id'], ref)
123 return {'service': ref}
124
125 @controller.protected
126 def list_services(self, context):
127 refs = self.catalog_api.list_services(context)
128 refs = self._filter_by_attribute(context, refs, 'type')
129 return {'services': self._paginate(context, refs)}
130
131 @controller.protected
132 def get_service(self, context, service_id):
133 ref = self.catalog_api.get_service(context, service_id)
134 return {'service': ref}
135
136 @controller.protected
137 def update_service(self, context, service_id, service):
138 self._require_matching_id(service_id, service)
139
140 ref = self.catalog_api.update_service(context, service_id, service)
141 return {'service': ref}
142
143 @controller.protected
144 def delete_service(self, context, service_id):
145 return self.catalog_api.delete_service(context, service_id)
146
147
148@dependency.requires('catalog_api')
149class EndpointV3(controller.V3Controller):
150 @controller.protected
151 def create_endpoint(self, context, endpoint):
152 ref = self._assign_unique_id(self._normalize_dict(endpoint))
153 self._require_attribute(ref, 'service_id')
154 self._require_attribute(ref, 'interface')
155 self.catalog_api.get_service(context, ref['service_id'])
156
157 ref = self.catalog_api.create_endpoint(context, ref['id'], ref)
158 return {'endpoint': ref}
159
160 @controller.protected
161 def list_endpoints(self, context):
162 refs = self.catalog_api.list_endpoints(context)
163 refs = self._filter_by_attribute(context, refs, 'service_id')
164 refs = self._filter_by_attribute(context, refs, 'interface')
165 return {'endpoints': self._paginate(context, refs)}
166
167 @controller.protected
168 def get_endpoint(self, context, endpoint_id):
169 ref = self.catalog_api.get_endpoint(context, endpoint_id)
170 return {'endpoint': ref}
171
172 @controller.protected
173 def update_endpoint(self, context, endpoint_id, endpoint):
174 self._require_matching_id(endpoint_id, endpoint)
175
176 if 'service_id' in endpoint:
177 self.catalog_api.get_service(context, endpoint['service_id'])
178
179 ref = self.catalog_api.update_endpoint(context, endpoint_id, endpoint)
180 return {'endpoint': ref}
181
182 @controller.protected
183 def delete_endpoint(self, context, endpoint_id):
184 return self.catalog_api.delete_endpoint(context, endpoint_id)
0185
=== modified file 'keystone/catalog/core.py'
--- keystone/catalog/core.py 2012-11-23 09:01:53 +0000
+++ keystone/catalog/core.py 2013-01-25 16:27:23 +0000
@@ -17,17 +17,11 @@
1717
18"""Main entry point into the Catalog service."""18"""Main entry point into the Catalog service."""
1919
20import uuid20from keystone.common import dependency
21
22from keystone.common import controller
23from keystone.common import logging21from keystone.common import logging
24from keystone.common import manager22from keystone.common import manager
25from keystone.common import wsgi
26from keystone import config23from keystone import config
27from keystone import exception24from keystone import exception
28from keystone import identity
29from keystone import policy
30from keystone import token
3125
3226
33CONF = config.CONF27CONF = config.CONF
@@ -41,21 +35,24 @@
41 except AttributeError:35 except AttributeError:
42 return None36 return None
43 except KeyError as e:37 except KeyError as e:
44 LOG.error("Malformed endpoint %s - unknown key %s" %38 LOG.error(_("Malformed endpoint %(url)s - unknown key %(keyerror)s") %
45 (url, str(e)))39 {"url": url,
40 "keyerror": str(e)})
46 raise exception.MalformedEndpoint(endpoint=url)41 raise exception.MalformedEndpoint(endpoint=url)
47 except TypeError as e:42 except TypeError as e:
48 LOG.error("Malformed endpoint %s - type mismatch %s \43 LOG.error(_("Malformed endpoint %(url)s - unknown key %(keyerror)s"
49 (are you missing brackets ?)" %44 "(are you missing brackets ?)") %
50 (url, str(e)))45 {"url": url,
46 "keyerror": str(e)})
51 raise exception.MalformedEndpoint(endpoint=url)47 raise exception.MalformedEndpoint(endpoint=url)
52 except ValueError as e:48 except ValueError as e:
53 LOG.error("Malformed endpoint %s - incomplete format \49 LOG.error(_("Malformed endpoint %s - incomplete format \
54 (are you missing a type notifier ?)" % url)50 (are you missing a type notifier ?)") % url)
55 raise exception.MalformedEndpoint(endpoint=url)51 raise exception.MalformedEndpoint(endpoint=url)
56 return result52 return result
5753
5854
55@dependency.provider('catalog_api')
59class Manager(manager.Manager):56class Manager(manager.Manager):
60 """Default pivot point for the Catalog backend.57 """Default pivot point for the Catalog backend.
6158
@@ -216,132 +213,3 @@
216213
217 """214 """
218 raise exception.NotImplemented()215 raise exception.NotImplemented()
219
220
221class ServiceController(wsgi.Application):
222 def __init__(self):
223 self.catalog_api = Manager()
224 self.identity_api = identity.Manager()
225 self.policy_api = policy.Manager()
226 self.token_api = token.Manager()
227 super(ServiceController, self).__init__()
228
229 def get_services(self, context):
230 self.assert_admin(context)
231 service_list = self.catalog_api.list_services(context)
232 return {'OS-KSADM:services': service_list}
233
234 def get_service(self, context, service_id):
235 self.assert_admin(context)
236 service_ref = self.catalog_api.get_service(context, service_id)
237 return {'OS-KSADM:service': service_ref}
238
239 def delete_service(self, context, service_id):
240 self.assert_admin(context)
241 self.catalog_api.delete_service(context, service_id)
242
243 def create_service(self, context, OS_KSADM_service):
244 self.assert_admin(context)
245 service_id = uuid.uuid4().hex
246 service_ref = OS_KSADM_service.copy()
247 service_ref['id'] = service_id
248 new_service_ref = self.catalog_api.create_service(
249 context, service_id, service_ref)
250 return {'OS-KSADM:service': new_service_ref}
251
252
253class EndpointController(wsgi.Application):
254 def __init__(self):
255 self.catalog_api = Manager()
256 self.identity_api = identity.Manager()
257 self.policy_api = policy.Manager()
258 self.token_api = token.Manager()
259 super(EndpointController, self).__init__()
260
261 def get_endpoints(self, context):
262 self.assert_admin(context)
263 endpoint_list = self.catalog_api.list_endpoints(context)
264 return {'endpoints': endpoint_list}
265
266 def create_endpoint(self, context, endpoint):
267 self.assert_admin(context)
268 endpoint_id = uuid.uuid4().hex
269 endpoint_ref = endpoint.copy()
270 endpoint_ref['id'] = endpoint_id
271 new_endpoint_ref = self.catalog_api.create_endpoint(
272 context, endpoint_id, endpoint_ref)
273 return {'endpoint': new_endpoint_ref}
274
275 def delete_endpoint(self, context, endpoint_id):
276 self.assert_admin(context)
277 self.catalog_api.delete_endpoint(context, endpoint_id)
278
279
280class ServiceControllerV3(controller.V3Controller):
281 @controller.protected
282 def create_service(self, context, service):
283 ref = self._assign_unique_id(self._normalize_dict(service))
284 self._require_attribute(ref, 'type')
285
286 ref = self.catalog_api.create_service(context, ref['id'], ref)
287 return {'service': ref}
288
289 @controller.protected
290 def list_services(self, context):
291 refs = self.catalog_api.list_services(context)
292 refs = self._filter_by_attribute(context, refs, 'type')
293 return {'services': self._paginate(context, refs)}
294
295 @controller.protected
296 def get_service(self, context, service_id):
297 ref = self.catalog_api.get_service(context, service_id)
298 return {'service': ref}
299
300 @controller.protected
301 def update_service(self, context, service_id, service):
302 self._require_matching_id(service_id, service)
303
304 ref = self.catalog_api.update_service(context, service_id, service)
305 return {'service': ref}
306
307 @controller.protected
308 def delete_service(self, context, service_id):
309 return self.catalog_api.delete_service(context, service_id)
310
311
312class EndpointControllerV3(controller.V3Controller):
313 @controller.protected
314 def create_endpoint(self, context, endpoint):
315 ref = self._assign_unique_id(self._normalize_dict(endpoint))
316 self._require_attribute(ref, 'service_id')
317 self._require_attribute(ref, 'interface')
318 self.catalog_api.get_service(context, ref['service_id'])
319
320 ref = self.catalog_api.create_endpoint(context, ref['id'], ref)
321 return {'endpoint': ref}
322
323 @controller.protected
324 def list_endpoints(self, context):
325 refs = self.catalog_api.list_endpoints(context)
326 refs = self._filter_by_attribute(context, refs, 'service_id')
327 refs = self._filter_by_attribute(context, refs, 'interface')
328 return {'endpoints': self._paginate(context, refs)}
329
330 @controller.protected
331 def get_endpoint(self, context, endpoint_id):
332 ref = self.catalog_api.get_endpoint(context, endpoint_id)
333 return {'endpoint': ref}
334
335 @controller.protected
336 def update_endpoint(self, context, endpoint_id, endpoint):
337 self._require_matching_id(endpoint_id, endpoint)
338
339 if 'service_id' in endpoint:
340 self.catalog_api.get_service(context, endpoint['service_id'])
341
342 ref = self.catalog_api.update_endpoint(context, endpoint_id, endpoint)
343 return {'endpoint': ref}
344
345 @controller.protected
346 def delete_endpoint(self, context, endpoint_id):
347 return self.catalog_api.delete_endpoint(context, endpoint_id)
348216
=== added file 'keystone/catalog/routers.py'
--- keystone/catalog/routers.py 1970-01-01 00:00:00 +0000
+++ keystone/catalog/routers.py 2013-01-25 16:27:23 +0000
@@ -0,0 +1,25 @@
1# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Copyright 2012 OpenStack LLC
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
17from keystone.catalog import controllers
18from keystone.common import router
19
20
21def append_v3_routers(mapper, routers):
22 routers.append(router.Router(controllers.ServiceV3(),
23 'services', 'service'))
24 routers.append(router.Router(controllers.EndpointV3(),
25 'endpoints', 'endpoint'))
026
=== modified file 'keystone/clean.py'
--- keystone/clean.py 2012-11-23 09:01:53 +0000
+++ keystone/clean.py 2013-01-25 16:27:23 +0000
@@ -20,20 +20,21 @@
20def check_length(property_name, value, min_length=1, max_length=64):20def check_length(property_name, value, min_length=1, max_length=64):
21 if len(value) < min_length:21 if len(value) < min_length:
22 if min_length == 1:22 if min_length == 1:
23 msg = "%s cannot be empty." % property_name23 msg = _("%s cannot be empty.") % property_name
24 else:24 else:
25 msg = ("%(property_name)s cannot be less than "25 msg = (_("%(property_name)s cannot be less than "
26 "%(min_length)s characters.") % locals()26 "%(min_length)s characters.")) % locals()
27 raise exception.ValidationError(msg)27 raise exception.ValidationError(msg)
28 if len(value) > max_length:28 if len(value) > max_length:
29 msg = ("%(property_name)s should not be greater than "29 msg = (_("%(property_name)s should not be greater than "
30 "%(max_length)s characters.") % locals()30 "%(max_length)s characters.")) % locals()
31 raise exception.ValidationError(msg)31 raise exception.ValidationError(msg)
3232
3333
34def check_type(property_name, value, expected_type, display_expected_type):34def check_type(property_name, value, expected_type, display_expected_type):
35 if not isinstance(value, expected_type):35 if not isinstance(value, expected_type):
36 msg = "%(property_name)s is not a %(display_expected_type)s" % locals()36 msg = _("%(property_name)s is not a"
37 "%(display_expected_type)s") % locals()
37 raise exception.ValidationError(msg)38 raise exception.ValidationError(msg)
3839
3940
@@ -54,3 +55,7 @@
5455
55def user_name(name):56def user_name(name):
56 return check_name('User', name)57 return check_name('User', name)
58
59
60def group_name(name):
61 return check_name('Group', name)
5762
=== modified file 'keystone/cli.py'
--- keystone/cli.py 2012-07-06 10:37:01 +0000
+++ keystone/cli.py 2013-01-25 16:27:23 +0000
@@ -16,11 +16,9 @@
1616
17from __future__ import absolute_import17from __future__ import absolute_import
1818
19import sys
20import textwrap
21
22from keystone import config19from keystone import config
23from keystone.common import openssl20from keystone.common import openssl
21from keystone.openstack.common import cfg
24from keystone.openstack.common import importutils22from keystone.openstack.common import importutils
25from keystone.openstack.common import jsonutils23from keystone.openstack.common import jsonutils
2624
@@ -28,17 +26,14 @@
2826
2927
30class BaseApp(object):28class BaseApp(object):
31 def __init__(self, argv=None):29
32 self.argv = argv30 name = None
3331
34 def run(self):32 @classmethod
35 return self.main()33 def add_argument_parser(cls, subparsers):
3634 parser = subparsers.add_parser(cls.name, help=cls.__doc__)
37 def missing_param(self, param):35 parser.set_defaults(cmd_class=cls)
38 print 'Missing parameter: %s' % param36 return parser
39 CONF.print_help()
40 print_commands(CMDS)
41 sys.exit(1)
4237
4338
44class DbSync(BaseApp):39class DbSync(BaseApp):
@@ -46,10 +41,8 @@
4641
47 name = 'db_sync'42 name = 'db_sync'
4843
49 def __init__(self, *args, **kw):44 @staticmethod
50 super(DbSync, self).__init__(*args, **kw)45 def main():
51
52 def main(self):
53 for k in ['identity', 'catalog', 'policy', 'token']:46 for k in ['identity', 'catalog', 'policy', 'token']:
54 driver = importutils.import_object(getattr(CONF, k).driver)47 driver = importutils.import_object(getattr(CONF, k).driver)
55 if hasattr(driver, 'db_sync'):48 if hasattr(driver, 'db_sync'):
@@ -61,10 +54,8 @@
6154
62 name = 'pki_setup'55 name = 'pki_setup'
6356
64 def __init__(self, *args, **kw):57 @staticmethod
65 super(PKISetup, self).__init__(*args, **kw)58 def main():
66
67 def main(self):
68 conf_ssl = openssl.ConfigurePKI()59 conf_ssl = openssl.ConfigurePKI()
69 conf_ssl.run()60 conf_ssl.run()
7061
@@ -74,15 +65,16 @@
7465
75 name = 'import_legacy'66 name = 'import_legacy'
7667
77 def __init__(self, *args, **kw):68 @classmethod
78 super(ImportLegacy, self).__init__(*args, **kw)69 def add_argument_parser(cls, subparsers):
70 parser = super(ImportLegacy, cls).add_argument_parser(subparsers)
71 parser.add_argument('old_db')
72 return parser
7973
80 def main(self):74 @staticmethod
75 def main():
81 from keystone.common.sql import legacy76 from keystone.common.sql import legacy
82 if len(self.argv) < 2:77 migration = legacy.LegacyMigration(CONF.command.old_db)
83 return self.missing_param('old_db')
84 old_db = self.argv[1]
85 migration = legacy.LegacyMigration(old_db)
86 migration.migrate_all()78 migration.migrate_all()
8779
8880
@@ -91,15 +83,17 @@
9183
92 name = 'export_legacy_catalog'84 name = 'export_legacy_catalog'
9385
94 def __init__(self, *args, **kw):86 @classmethod
95 super(ExportLegacyCatalog, self).__init__(*args, **kw)87 def add_argument_parser(cls, subparsers):
88 parser = super(ExportLegacyCatalog,
89 cls).add_argument_parser(subparsers)
90 parser.add_argument('old_db')
91 return parser
9692
97 def main(self):93 @staticmethod
94 def main():
98 from keystone.common.sql import legacy95 from keystone.common.sql import legacy
99 if len(self.argv) < 2:96 migration = legacy.LegacyMigration(CONF.command.old_db)
100 return self.missing_param('old_db')
101 old_db = self.argv[1]
102 migration = legacy.LegacyMigration(old_db)
103 print '\n'.join(migration.dump_catalog())97 print '\n'.join(migration.dump_catalog())
10498
10599
@@ -108,60 +102,43 @@
108102
109 name = 'import_nova_auth'103 name = 'import_nova_auth'
110104
111 def __init__(self, *args, **kw):105 @classmethod
112 super(ImportNovaAuth, self).__init__(*args, **kw)106 def add_argument_parser(cls, subparsers):
107 parser = super(ImportNovaAuth, cls).add_argument_parser(subparsers)
108 parser.add_argument('dump_file')
109 return parser
113110
114 def main(self):111 @staticmethod
112 def main():
115 from keystone.common.sql import nova113 from keystone.common.sql import nova
116 if len(self.argv) < 2:114 dump_data = jsonutils.loads(open(CONF.command.dump_file).read())
117 return self.missing_param('dump_file')
118 dump_file = self.argv[1]
119 dump_data = jsonutils.loads(open(dump_file).read())
120 nova.import_auth(dump_data)115 nova.import_auth(dump_data)
121116
122117
123CMDS = {'db_sync': DbSync,118CMDS = [
124 'import_legacy': ImportLegacy,119 DbSync,
125 'export_legacy_catalog': ExportLegacyCatalog,120 ExportLegacyCatalog,
126 'import_nova_auth': ImportNovaAuth,121 ImportLegacy,
127 'pki_setup': PKISetup,122 ImportNovaAuth,
128 }123 PKISetup,
129124]
130125
131def print_commands(cmds):126
132 print127def add_command_parsers(subparsers):
133 print 'Available commands:'128 for cmd in CMDS:
134 o = []129 cmd.add_argument_parser(subparsers)
135 max_length = max([len(k) for k in cmds]) + 2130
136 for k, cmd in sorted(cmds.iteritems()):131
137 initial_indent = '%s%s: ' % (' ' * (max_length - len(k)), k)132command_opt = cfg.SubCommandOpt('command',
138 tw = textwrap.TextWrapper(initial_indent=initial_indent,133 title='Commands',
139 subsequent_indent=' ' * (max_length + 2),134 help='Available commands',
140 width=80)135 handler=add_command_parsers)
141 o.extend(tw.wrap(
142 (cmd.__doc__ and cmd.__doc__ or 'no docs').strip().split('\n')[0]))
143 print '\n'.join(o)
144
145
146def run(cmd, args):
147 return CMDS[cmd](argv=args).run()
148136
149137
150def main(argv=None, config_files=None):138def main(argv=None, config_files=None):
151 CONF.reset()139 CONF.register_cli_opt(command_opt)
152 args = CONF(args=argv,140 CONF(args=argv[1:],
153 project='keystone',141 project='keystone',
154 usage='%prog COMMAND',142 usage='%(prog)s [' + '|'.join([cmd.name for cmd in CMDS]) + ']',
155 default_config_files=config_files)143 default_config_files=config_files)
156144 CONF.command.cmd_class.main()
157 if len(args) < 2:
158 CONF.print_help()
159 print_commands(CMDS)
160 sys.exit(1)
161
162 cmd = args[1]
163 if cmd in CMDS:
164 return run(cmd, (args[:1] + args[2:]))
165 else:
166 print_commands(CMDS)
167 sys.exit("Unknown command: %s" % cmd)
168145
=== modified file 'keystone/common/bufferedhttp.py'
--- keystone/common/bufferedhttp.py 2012-11-23 09:01:53 +0000
+++ keystone/common/bufferedhttp.py 2013-01-25 16:27:23 +0000
@@ -99,8 +99,8 @@
9999
100 def getresponse(self):100 def getresponse(self):
101 response = HTTPConnection.getresponse(self)101 response = HTTPConnection.getresponse(self)
102 LOG.debug('HTTP PERF: %(time).5f seconds to %(method)s '102 LOG.debug(_('HTTP PERF: %(time).5f seconds to %(method)s '
103 '%(host)s:%(port)s %(path)s)',103 '%(host)s:%(port)s %(path)s)'),
104 {'time': time.time() - self._connected_time,104 {'time': time.time() - self._connected_time,
105 'method': self._method,105 'method': self._method,
106 'host': self.host,106 'host': self.host,
107107
=== modified file 'keystone/common/cms.py'
--- keystone/common/cms.py 2012-11-23 09:01:53 +0000
+++ keystone/common/cms.py 2013-01-25 16:27:23 +0000
@@ -41,7 +41,7 @@
41 output, err = process.communicate(formatted)41 output, err = process.communicate(formatted)
42 retcode = process.poll()42 retcode = process.poll()
43 if retcode:43 if retcode:
44 LOG.error('Verify error: %s' % err)44 LOG.error(_('Verify error: %s') % err)
45 raise subprocess.CalledProcessError(retcode, "openssl", output=err)45 raise subprocess.CalledProcessError(retcode, "openssl", output=err)
46 return output46 return output
4747
@@ -131,7 +131,7 @@
131 output, err = process.communicate(text)131 output, err = process.communicate(text)
132 retcode = process.poll()132 retcode = process.poll()
133 if retcode or "Error" in err:133 if retcode or "Error" in err:
134 LOG.error('Signing error: %s' % err)134 LOG.error(_('Signing error: %s') % err)
135 raise subprocess.CalledProcessError(retcode, "openssl")135 raise subprocess.CalledProcessError(retcode, "openssl")
136 return output136 return output
137137
138138
=== modified file 'keystone/common/controller.py'
--- keystone/common/controller.py 2012-11-23 09:01:53 +0000
+++ keystone/common/controller.py 2013-01-25 16:27:23 +0000
@@ -1,6 +1,7 @@
1import uuid1import uuid
2import functools2import functools
33
4from keystone.common import dependency
4from keystone.common import logging5from keystone.common import logging
5from keystone.common import wsgi6from keystone.common import wsgi
6from keystone import exception7from keystone import exception
@@ -17,15 +18,15 @@
17 if not context['is_admin']:18 if not context['is_admin']:
18 action = 'identity:%s' % f.__name__19 action = 'identity:%s' % f.__name__
1920
20 LOG.debug('RBAC: Authorizing %s(%s)' % (21 LOG.debug(_('RBAC: Authorizing %s(%s)' % (
21 action,22 action,
22 ', '.join(['%s=%s' % (k, kwargs[k]) for k in kwargs])))23 ', '.join(['%s=%s' % (k, kwargs[k]) for k in kwargs]))))
2324
24 try:25 try:
25 token_ref = self.token_api.get_token(26 token_ref = self.token_api.get_token(
26 context=context, token_id=context['token_id'])27 context=context, token_id=context['token_id'])
27 except exception.TokenNotFound:28 except exception.TokenNotFound:
28 LOG.warning('RBAC: Invalid token')29 LOG.warning(_('RBAC: Invalid token'))
29 raise exception.Unauthorized()30 raise exception.Unauthorized()
3031
31 creds = token_ref['metadata'].copy()32 creds = token_ref['metadata'].copy()
@@ -33,13 +34,13 @@
33 try:34 try:
34 creds['user_id'] = token_ref['user'].get('id')35 creds['user_id'] = token_ref['user'].get('id')
35 except AttributeError:36 except AttributeError:
36 LOG.warning('RBAC: Invalid user')37 LOG.warning(_('RBAC: Invalid user'))
37 raise exception.Unauthorized()38 raise exception.Unauthorized()
3839
39 try:40 try:
40 creds['tenant_id'] = token_ref['tenant'].get('id')41 creds['tenant_id'] = token_ref['tenant'].get('id')
41 except AttributeError:42 except AttributeError:
42 LOG.debug('RBAC: Proceeding without tenant')43 LOG.debug(_('RBAC: Proceeding without tenant'))
4344
44 # NOTE(vish): this is pretty inefficient45 # NOTE(vish): this is pretty inefficient
45 creds['roles'] = [self.identity_api.get_role(context, role)['name']46 creds['roles'] = [self.identity_api.get_role(context, role)['name']
@@ -47,24 +48,23 @@
4748
48 self.policy_api.enforce(context, creds, action, kwargs)49 self.policy_api.enforce(context, creds, action, kwargs)
4950
50 LOG.debug('RBAC: Authorization granted')51 LOG.debug(_('RBAC: Authorization granted'))
51 else:52 else:
52 LOG.warning('RBAC: Bypassing authorization')53 LOG.warning(_('RBAC: Bypassing authorization'))
5354
54 return f(self, context, **kwargs)55 return f(self, context, **kwargs)
55 return wrapper56 return wrapper
5657
5758
58class V3Controller(wsgi.Application):59@dependency.requires('identity_api', 'policy_api', 'token_api')
60class V2Controller(wsgi.Application):
61 """Base controller class for Identity API v2."""
62 pass
63
64
65class V3Controller(V2Controller):
59 """Base controller class for Identity API v3."""66 """Base controller class for Identity API v3."""
6067
61 def __init__(self, catalog_api, identity_api, token_api, policy_api):
62 self.catalog_api = catalog_api
63 self.identity_api = identity_api
64 self.policy_api = policy_api
65 self.token_api = token_api
66 super(V3Controller, self).__init__()
67
68 def _paginate(self, context, refs):68 def _paginate(self, context, refs):
69 """Paginates a list of references by page & per_page query strings."""69 """Paginates a list of references by page & per_page query strings."""
70 page = context['query_string'].get('page', 1)70 page = context['query_string'].get('page', 1)
7171
=== added file 'keystone/common/dependency.py'
--- keystone/common/dependency.py 1970-01-01 00:00:00 +0000
+++ keystone/common/dependency.py 2013-01-25 16:27:23 +0000
@@ -0,0 +1,67 @@
1# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Copyright 2012 OpenStack LLC
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
17REGISTRY = {}
18
19
20class UnresolvableDependencyException(Exception):
21 def __init__(self, name):
22 msg = 'Unregistered dependency: %s' % name
23 super(UnresolvableDependencyException, self).__init__(msg)
24
25
26def provider(name):
27 """Register the wrapped dependency provider under the specified name."""
28 def wrapper(cls):
29 def wrapped(init):
30 def __wrapped_init__(self, *args, **kwargs):
31 """Initialize the wrapped object and add it to the registry."""
32 init(self, *args, **kwargs)
33 REGISTRY[name] = self
34
35 return __wrapped_init__
36
37 cls.__init__ = wrapped(cls.__init__)
38 return cls
39
40 return wrapper
41
42
43def requires(*dependencies):
44 """Inject specified dependencies from the registry into the instance."""
45 def wrapper(self, *args, **kwargs):
46 """Inject each dependency from the registry."""
47 self.__wrapped_init__(*args, **kwargs)
48
49 for dependency in self._dependencies:
50 if dependency not in REGISTRY:
51 raise UnresolvableDependencyException(dependency)
52 setattr(self, dependency, REGISTRY[dependency])
53
54 def wrapped(cls):
55 """Note the required dependencies on the object for later injection.
56
57 The dependencies of the parent class are combined with that of the
58 child class to create a new set of dependencies.
59 """
60 existing_dependencies = getattr(cls, '_dependencies', set())
61 cls._dependencies = existing_dependencies.union(dependencies)
62 if not hasattr(cls, '__wrapped_init__'):
63 cls.__wrapped_init__ = cls.__init__
64 cls.__init__ = wrapper
65 return cls
66
67 return wrapped
068
=== modified file 'keystone/common/ldap/core.py'
--- keystone/common/ldap/core.py 2012-11-23 09:01:53 +0000
+++ keystone/common/ldap/core.py 2013-01-25 16:27:23 +0000
@@ -168,8 +168,8 @@
168 pass168 pass
169 else:169 else:
170 raise exception.Conflict(type=self.options_name,170 raise exception.Conflict(type=self.options_name,
171 details='Duplicate name, %s.' %171 details=_('Duplicate name, %s.') %
172 values['name'])172 values['name'])
173173
174 if values.get('id') is not None:174 if values.get('id') is not None:
175 try:175 try:
@@ -178,12 +178,13 @@
178 pass178 pass
179 else:179 else:
180 raise exception.Conflict(type=self.options_name,180 raise exception.Conflict(type=self.options_name,
181 details='Duplicate ID, %s.' %181 details=_('Duplicate ID, %s.') %
182 values['id'])182 values['id'])
183183
184 def create(self, values):184 def create(self, values):
185 if not self.allow_create:185 if not self.allow_create:
186 msg = 'LDAP backend does not allow %s create' % self.options_name186 msg = _('LDAP backend does not allow %s create') \
187 % self.options_name
187 raise exception.ForbiddenAction(msg)188 raise exception.ForbiddenAction(msg)
188189
189 conn = self.get_connection()190 conn = self.get_connection()
@@ -289,7 +290,8 @@
289290
290 def update(self, id, values, old_obj=None):291 def update(self, id, values, old_obj=None):
291 if not self.allow_update:292 if not self.allow_update:
292 msg = 'LDAP backend does not allow %s update' % self.options_name293 msg = _('LDAP backend does not allow %s update') \
294 % self.options_name
293 raise exception.ForbiddenAction(msg)295 raise exception.ForbiddenAction(msg)
294296
295 if old_obj is None:297 if old_obj is None:
@@ -316,7 +318,8 @@
316318
317 def delete(self, id):319 def delete(self, id):
318 if not self.allow_delete:320 if not self.allow_delete:
319 msg = 'LDAP backend does not allow %s delete' % self.options_name321 msg = _('LDAP backend does not allow %s delete') \
322 % self.options_name
320 raise exception.ForbiddenAction(msg)323 raise exception.ForbiddenAction(msg)
321324
322 conn = self.get_connection()325 conn = self.get_connection()
@@ -333,11 +336,11 @@
333336
334class LdapWrapper(object):337class LdapWrapper(object):
335 def __init__(self, url):338 def __init__(self, url):
336 LOG.debug("LDAP init: url=%s", url)339 LOG.debug(_("LDAP init: url=%s", url))
337 self.conn = ldap.initialize(url)340 self.conn = ldap.initialize(url)
338341
339 def simple_bind_s(self, user, password):342 def simple_bind_s(self, user, password):
340 LOG.debug("LDAP bind: dn=%s", user)343 LOG.debug(_("LDAP bind: dn=%s", user))
341 return self.conn.simple_bind_s(user, password)344 return self.conn.simple_bind_s(user, password)
342345
343 def add_s(self, dn, attrs):346 def add_s(self, dn, attrs):
@@ -348,15 +351,15 @@
348 if kind != 'userPassword'351 if kind != 'userPassword'
349 else ['****'])352 else ['****'])
350 for kind, values in ldap_attrs]353 for kind, values in ldap_attrs]
351 LOG.debug('LDAP add: dn=%s, attrs=%s', dn, sane_attrs)354 LOG.debug(_('LDAP add: dn=%s, attrs=%s', dn, sane_attrs))
352 return self.conn.add_s(dn, ldap_attrs)355 return self.conn.add_s(dn, ldap_attrs)
353356
354 def search_s(self, dn, scope, query):357 def search_s(self, dn, scope, query):
355 if LOG.isEnabledFor(logging.DEBUG):358 if LOG.isEnabledFor(logging.DEBUG):
356 LOG.debug('LDAP search: dn=%s, scope=%s, query=%s',359 LOG.debug(_('LDAP search: dn=%s, scope=%s, query=%s',
357 dn,360 dn,
358 scope,361 scope,
359 query)362 query))
360 res = self.conn.search_s(dn, scope, query)363 res = self.conn.search_s(dn, scope, query)
361364
362 o = []365 o = []
@@ -376,14 +379,14 @@
376 sane_modlist = [(op, kind, (values if kind != 'userPassword'379 sane_modlist = [(op, kind, (values if kind != 'userPassword'
377 else ['****']))380 else ['****']))
378 for op, kind, values in ldap_modlist]381 for op, kind, values in ldap_modlist]
379 LOG.debug("LDAP modify: dn=%s, modlist=%s", dn, sane_modlist)382 LOG.debug(_("LDAP modify: dn=%s, modlist=%s", dn, sane_modlist))
380383
381 return self.conn.modify_s(dn, ldap_modlist)384 return self.conn.modify_s(dn, ldap_modlist)
382385
383 def delete_s(self, dn):386 def delete_s(self, dn):
384 LOG.debug("LDAP delete: dn=%s", dn)387 LOG.debug(_("LDAP delete: dn=%s", dn))
385 return self.conn.delete_s(dn)388 return self.conn.delete_s(dn)
386389
387 def delete_ext_s(self, dn, serverctrls):390 def delete_ext_s(self, dn, serverctrls):
388 LOG.debug("LDAP delete_ext: dn=%s, serverctrls=%s", dn, serverctrls)391 LOG.debug(_("LDAP delete_ext: dn=%s, serverctrls=%s", dn, serverctrls))
389 return self.conn.delete_ext_s(dn, serverctrls)392 return self.conn.delete_ext_s(dn, serverctrls)
390393
=== modified file 'keystone/common/ldap/fakeldap.py'
--- keystone/common/ldap/fakeldap.py 2012-11-02 13:48:49 +0000
+++ keystone/common/ldap/fakeldap.py 2013-01-25 16:27:23 +0000
@@ -145,7 +145,7 @@
145 __prefix = 'ldap:'145 __prefix = 'ldap:'
146146
147 def __init__(self, url):147 def __init__(self, url):
148 LOG.debug('FakeLdap initialize url=%s', url)148 LOG.debug(_('FakeLdap initialize url=%s'), url)
149 if url == 'fake://memory':149 if url == 'fake://memory':
150 self.db = FakeShelve.get_instance()150 self.db = FakeShelve.get_instance()
151 else:151 else:
@@ -155,26 +155,27 @@
155 """This method is ignored, but provided for compatibility."""155 """This method is ignored, but provided for compatibility."""
156 if server_fail:156 if server_fail:
157 raise ldap.SERVER_DOWN157 raise ldap.SERVER_DOWN
158 LOG.debug('FakeLdap bind dn=%s', dn)158 LOG.debug(_('FakeLdap bind dn=%s'), dn)
159 if dn == 'cn=Admin' and password == 'password':159 if dn == 'cn=Admin' and password == 'password':
160 return160 return
161161
162 try:162 try:
163 attrs = self.db['%s%s' % (self.__prefix, dn)]163 attrs = self.db['%s%s' % (self.__prefix, dn)]
164 except KeyError:164 except KeyError:
165 LOG.error('FakeLdap bind fail: dn=%s not found', dn)165 LOG.error(_('FakeLdap bind fail: dn=%s not found'), dn)
166 raise ldap.NO_SUCH_OBJECT166 raise ldap.NO_SUCH_OBJECT
167167
168 db_password = None168 db_password = None
169 try:169 try:
170 db_password = attrs['userPassword'][0]170 db_password = attrs['userPassword'][0]
171 except (KeyError, IndexError):171 except (KeyError, IndexError):
172 LOG.error('FakeLdap bind fail: password for dn=%s not found', dn)172 LOG.error(_('FakeLdap bind fail: password for dn=%s not found'),
173 dn)
173 raise ldap.INAPPROPRIATE_AUTH174 raise ldap.INAPPROPRIATE_AUTH
174175
175 if not utils.ldap_check_password(password, db_password):176 if not utils.ldap_check_password(password, db_password):
176 LOG.error('FakeLdap bind fail: password for dn=%s does'177 LOG.error(_('FakeLdap bind fail: password for dn=%s does'
177 ' not match' % dn)178 ' not match') % dn)
178 raise ldap.INVALID_CREDENTIALS179 raise ldap.INVALID_CREDENTIALS
179180
180 def unbind_s(self):181 def unbind_s(self):
@@ -188,10 +189,10 @@
188 raise ldap.SERVER_DOWN189 raise ldap.SERVER_DOWN
189190
190 key = '%s%s' % (self.__prefix, dn)191 key = '%s%s' % (self.__prefix, dn)
191 LOG.debug('FakeLdap add item: dn=%s, attrs=%s', dn, attrs)192 LOG.debug(_('FakeLdap add item: dn=%s, attrs=%s'), dn, attrs)
192 if key in self.db:193 if key in self.db:
193 LOG.error('FakeLdap add item failed: dn=%s is'194 LOG.error(_('FakeLdap add item failed: dn=%s is'
194 ' already in store.', dn)195 ' already in store.'), dn)
195 raise ldap.ALREADY_EXISTS(dn)196 raise ldap.ALREADY_EXISTS(dn)
196197
197 self.db[key] = dict([(k, v if isinstance(v, list) else [v])198 self.db[key] = dict([(k, v if isinstance(v, list) else [v])
@@ -204,11 +205,11 @@
204 raise ldap.SERVER_DOWN205 raise ldap.SERVER_DOWN
205206
206 key = '%s%s' % (self.__prefix, dn)207 key = '%s%s' % (self.__prefix, dn)
207 LOG.debug('FakeLdap delete item: dn=%s', dn)208 LOG.debug(_('FakeLdap delete item: dn=%s'), dn)
208 try:209 try:
209 del self.db[key]210 del self.db[key]
210 except KeyError:211 except KeyError:
211 LOG.error('FakeLdap delete item failed: dn=%s not found.', dn)212 LOG.error(_('FakeLdap delete item failed: dn=%s not found.'), dn)
212 raise ldap.NO_SUCH_OBJECT213 raise ldap.NO_SUCH_OBJECT
213 self.db.sync()214 self.db.sync()
214215
@@ -218,11 +219,11 @@
218 raise ldap.SERVER_DOWN219 raise ldap.SERVER_DOWN
219220
220 key = '%s%s' % (self.__prefix, dn)221 key = '%s%s' % (self.__prefix, dn)
221 LOG.debug('FakeLdap delete item: dn=%s', dn)222 LOG.debug(_('FakeLdap delete item: dn=%s'), dn)
222 try:223 try:
223 del self.db[key]224 del self.db[key]
224 except KeyError:225 except KeyError:
225 LOG.error('FakeLdap delete item failed: dn=%s not found.', dn)226 LOG.error(_('FakeLdap delete item failed: dn=%s not found.'), dn)
226 raise ldap.NO_SUCH_OBJECT227 raise ldap.NO_SUCH_OBJECT
227 self.db.sync()228 self.db.sync()
228229
@@ -237,11 +238,11 @@
237 raise ldap.SERVER_DOWN238 raise ldap.SERVER_DOWN
238239
239 key = '%s%s' % (self.__prefix, dn)240 key = '%s%s' % (self.__prefix, dn)
240 LOG.debug('FakeLdap modify item: dn=%s attrs=%s', dn, attrs)241 LOG.debug(_('FakeLdap modify item: dn=%s attrs=%s'), dn, attrs)
241 try:242 try:
242 entry = self.db[key]243 entry = self.db[key]
243 except KeyError:244 except KeyError:
244 LOG.error('FakeLdap modify item failed: dn=%s not found.', dn)245 LOG.error(_('FakeLdap modify item failed: dn=%s not found.'), dn)
245 raise ldap.NO_SUCH_OBJECT246 raise ldap.NO_SUCH_OBJECT
246247
247 for cmd, k, v in attrs:248 for cmd, k, v in attrs:
@@ -258,8 +259,8 @@
258 elif cmd == ldap.MOD_DELETE:259 elif cmd == ldap.MOD_DELETE:
259 if v is None:260 if v is None:
260 if len(values) == 0:261 if len(values) == 0:
261 LOG.error('FakeLdap modify item failed: '262 LOG.error(_('FakeLdap modify item failed: '
262 'item has no attribute "%s" to delete', k)263 'item has no attribute "%s" to delete'), k)
263 raise ldap.NO_SUCH_ATTRIBUTE264 raise ldap.NO_SUCH_ATTRIBUTE
264 values[:] = []265 values[:] = []
265 else:266 else:
@@ -269,15 +270,15 @@
269 try:270 try:
270 values.remove(val)271 values.remove(val)
271 except ValueError:272 except ValueError:
272 LOG.error('FakeLdap modify item failed:'273 LOG.error(_('FakeLdap modify item failed:'
273 ' item has no attribute "%s" with'274 ' item has no attribute "%s" with'
274 ' value "%s" to delete', k, val)275 ' value "%s" to delete'), k, val)
275 raise ldap.NO_SUCH_ATTRIBUTE276 raise ldap.NO_SUCH_ATTRIBUTE
276 else:277 else:
277 LOG.error('FakeLdap modify item failed: unknown'278 LOG.error(_('FakeLdap modify item failed: unknown'
278 ' command %s', cmd)279 ' command %s'), cmd)
279 raise NotImplementedError('modify_s action %s not implemented'280 raise NotImplementedError(_('modify_s action %s not'
280 % cmd)281 ' implemented') % cmd)
281 self.db[key] = entry282 self.db[key] = entry
282 self.db.sync()283 self.db.sync()
283284
@@ -294,13 +295,14 @@
294 if server_fail:295 if server_fail:
295 raise ldap.SERVER_DOWN296 raise ldap.SERVER_DOWN
296297
297 LOG.debug('FakeLdap search at dn=%s scope=%s query=%s',298 LOG.debug(_('FakeLdap search at dn=%s scope=%s query=%s'),
298 dn, SCOPE_NAMES.get(scope, scope), query)299 dn, SCOPE_NAMES.get(scope, scope), query)
299 if scope == ldap.SCOPE_BASE:300 if scope == ldap.SCOPE_BASE:
300 try:301 try:
301 item_dict = self.db['%s%s' % (self.__prefix, dn)]302 item_dict = self.db['%s%s' % (self.__prefix, dn)]
302 except KeyError:303 except KeyError:
303 LOG.debug('FakeLdap search fail: dn not found for SCOPE_BASE')304 LOG.debug(_('FakeLdap search fail: dn not found for'
305 ' SCOPE_BASE'))
304 raise ldap.NO_SUCH_OBJECT306 raise ldap.NO_SUCH_OBJECT
305 results = [(dn, item_dict)]307 results = [(dn, item_dict)]
306 elif scope == ldap.SCOPE_SUBTREE:308 elif scope == ldap.SCOPE_SUBTREE:
@@ -313,7 +315,7 @@
313 if re.match('%s\w+=[^,]+,%s' % (self.__prefix, dn), k)]315 if re.match('%s\w+=[^,]+,%s' % (self.__prefix, dn), k)]
314 else:316 else:
315 LOG.error('FakeLdap search fail: unknown scope %s', scope)317 LOG.error('FakeLdap search fail: unknown scope %s', scope)
316 raise NotImplementedError('Search scope %s not implemented.'318 raise NotImplementedError(_('Search scope %s not implemented.')
317 % scope)319 % scope)
318320
319 objects = []321 objects = []
320322
=== modified file 'keystone/common/models.py'
--- keystone/common/models.py 2012-11-02 13:48:49 +0000
+++ keystone/common/models.py 2013-01-25 16:27:23 +0000
@@ -78,7 +78,7 @@
78 """78 """
7979
80 required_keys = ('id', 'region', 'service_id')80 required_keys = ('id', 'region', 'service_id')
81 optional_keys = ('interalurl', 'publicurl', 'adminurl')81 optional_keys = ('internalurl', 'publicurl', 'adminurl')
8282
8383
84class User(Model):84class User(Model):
@@ -99,6 +99,23 @@
99 optional_keys = ('password', 'description', 'email', 'enabled')99 optional_keys = ('password', 'description', 'email', 'enabled')
100100
101101
102class Group(Model):
103 """Group object.
104
105 Required keys:
106 id
107 name
108
109 Optional keys:
110 domain_id
111 description
112
113 """
114
115 required_keys = ('id', 'name')
116 optional_keys = ('domain_id', 'description')
117
118
102class Tenant(Model):119class Tenant(Model):
103 """Tenant object.120 """Tenant object.
104121
105122
=== added file 'keystone/common/router.py'
--- keystone/common/router.py 1970-01-01 00:00:00 +0000
+++ keystone/common/router.py 2013-01-25 16:27:23 +0000
@@ -0,0 +1,56 @@
1# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Copyright 2012 OpenStack LLC
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16from keystone.common import wsgi
17
18
19class Router(wsgi.ComposableRouter):
20 def __init__(self, controller, collection_key, key):
21 self.controller = controller
22 self.key = key
23 self.collection_key = collection_key
24
25 def add_routes(self, mapper):
26 collection_path = '/%(collection_key)s' % {
27 'collection_key': self.collection_key}
28 entity_path = '/%(collection_key)s/{%(key)s_id}' % {
29 'collection_key': self.collection_key,
30 'key': self.key}
31
32 mapper.connect(
33 collection_path,
34 controller=self.controller,
35 action='create_%s' % self.key,
36 conditions=dict(method=['POST']))
37 mapper.connect(
38 collection_path,
39 controller=self.controller,
40 action='list_%s' % self.collection_key,
41 conditions=dict(method=['GET']))
42 mapper.connect(
43 entity_path,
44 controller=self.controller,
45 action='get_%s' % self.key,
46 conditions=dict(method=['GET']))
47 mapper.connect(
48 entity_path,
49 controller=self.controller,
50 action='update_%s' % self.key,
51 conditions=dict(method=['PATCH']))
52 mapper.connect(
53 entity_path,
54 controller=self.controller,
55 action='delete_%s' % self.key,
56 conditions=dict(method=['DELETE']))
057
=== modified file 'keystone/common/sql/core.py'
--- keystone/common/sql/core.py 2012-11-23 09:01:53 +0000
+++ keystone/common/sql/core.py 2013-01-25 16:27:23 +0000
@@ -46,6 +46,7 @@
46IntegrityError = sql.exc.IntegrityError46IntegrityError = sql.exc.IntegrityError
47NotFound = sql.orm.exc.NoResultFound47NotFound = sql.orm.exc.NoResultFound
48Boolean = sql.Boolean48Boolean = sql.Boolean
49Text = sql.Text
4950
5051
51def set_global_engine(engine):52def set_global_engine(engine):
@@ -159,7 +160,7 @@
159 dbapi_con.cursor().execute('select 1')160 dbapi_con.cursor().execute('select 1')
160 except dbapi_con.OperationalError as e:161 except dbapi_con.OperationalError as e:
161 if e.args[0] in (2006, 2013, 2014, 2045, 2055):162 if e.args[0] in (2006, 2013, 2014, 2045, 2055):
162 logging.warn('Got mysql server has gone away: %s', e)163 logging.warn(_('Got mysql server has gone away: %s'), e)
163 raise DisconnectionError("Database server went away")164 raise DisconnectionError("Database server went away")
164 else:165 else:
165 raise166 raise
166167
=== modified file 'keystone/common/sql/legacy.py'
--- keystone/common/sql/legacy.py 2012-08-16 13:59:29 +0000
+++ keystone/common/sql/legacy.py 2013-01-25 16:27:23 +0000
@@ -171,4 +171,4 @@
171 try:171 try:
172 self.ec2_driver.create_credential(None, new_dict)172 self.ec2_driver.create_credential(None, new_dict)
173 except exc.IntegrityError:173 except exc.IntegrityError:
174 LOG.exception('Cannot migrate EC2 credential: %s' % x)174 LOG.exception(_('Cannot migrate EC2 credential: %s') % x)
175175
=== modified file 'keystone/common/sql/migrate_repo/versions/001_add_initial_tables.py'
--- keystone/common/sql/migrate_repo/versions/001_add_initial_tables.py 2012-11-23 09:01:53 +0000
+++ keystone/common/sql/migrate_repo/versions/001_add_initial_tables.py 2013-01-25 16:27:23 +0000
@@ -14,7 +14,6 @@
14# License for the specific language governing permissions and limitations14# License for the specific language governing permissions and limitations
15# under the License.15# under the License.
1616
17import migrate
18import sqlalchemy as sql17import sqlalchemy as sql
1918
2019
@@ -116,4 +115,11 @@
116115
117def downgrade(migrate_engine):116def downgrade(migrate_engine):
118 # Operations to reverse the above upgrade go here.117 # Operations to reverse the above upgrade go here.
119 pass118 meta = sql.MetaData()
119 meta.bind = migrate_engine
120
121 tables = ['user_tenant_membership', 'token', 'user', 'tenant', 'role',
122 'metadata', 'ec2_credential', 'endpoint', 'service']
123 for t in tables:
124 table = sql.Table(t, meta, autoload=True)
125 table.drop(migrate_engine, checkfirst=True)
120126
=== removed file 'keystone/common/sql/migrate_repo/versions/003_sqlite_downgrade.sql'
--- keystone/common/sql/migrate_repo/versions/003_sqlite_downgrade.sql 2012-09-07 13:04:01 +0000
+++ keystone/common/sql/migrate_repo/versions/003_sqlite_downgrade.sql 1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
1alter TABLE token drop column valid;
20
=== modified file 'keystone/common/sql/migrate_repo/versions/003_token_valid.py'
--- keystone/common/sql/migrate_repo/versions/003_token_valid.py 2012-09-07 13:04:01 +0000
+++ keystone/common/sql/migrate_repo/versions/003_token_valid.py 2013-01-25 16:27:23 +0000
@@ -15,13 +15,9 @@
15# under the License.15# under the License.
1616
1717
18from migrate import *
19from sqlalchemy import *18from sqlalchemy import *
2019
2120
22from keystone.common import sql
23
24
25def upgrade(migrate_engine):21def upgrade(migrate_engine):
26 # Upgrade operations go here. Don't create your own engine; bind22 # Upgrade operations go here. Don't create your own engine; bind
2723
2824
=== modified file 'keystone/common/sql/migrate_repo/versions/006_add_policy_table.py'
--- keystone/common/sql/migrate_repo/versions/006_add_policy_table.py 2012-11-23 09:01:53 +0000
+++ keystone/common/sql/migrate_repo/versions/006_add_policy_table.py 2013-01-25 16:27:23 +0000
@@ -14,7 +14,6 @@
14# License for the specific language governing permissions and limitations14# License for the specific language governing permissions and limitations
15# under the License.15# under the License.
1616
17import migrate
18import sqlalchemy as sql17import sqlalchemy as sql
1918
2019
@@ -33,4 +32,8 @@
3332
3433
35def downgrade(migrate_engine):34def downgrade(migrate_engine):
36 pass35 meta = sql.MetaData()
36 meta.bind = migrate_engine
37
38 policy_table = sql.Table('policy', meta, autoload=True)
39 policy_table.drop(migrate_engine, checkfirst=True)
3740
=== modified file 'keystone/common/sql/migrate_repo/versions/007_add_domain_tables.py'
--- keystone/common/sql/migrate_repo/versions/007_add_domain_tables.py 2012-11-23 09:01:53 +0000
+++ keystone/common/sql/migrate_repo/versions/007_add_domain_tables.py 2013-01-25 16:27:23 +0000
@@ -14,7 +14,6 @@
14# License for the specific language governing permissions and limitations14# License for the specific language governing permissions and limitations
15# under the License.15# under the License.
1616
17import migrate
18import sqlalchemy as sql17import sqlalchemy as sql
1918
2019
@@ -77,3 +76,8 @@
7776
78 role = sql.Table('role', meta, autoload=True)77 role = sql.Table('role', meta, autoload=True)
79 role.drop_column('extra')78 role.drop_column('extra')
79
80 tables = ['domain', 'user_domain_metadata', 'credential']
81 for t in tables:
82 table = sql.Table(t, meta, autoload=True)
83 table.drop(migrate_engine, checkfirst=True)
8084
=== added file 'keystone/common/sql/migrate_repo/versions/008_normalize_identity.py'
--- keystone/common/sql/migrate_repo/versions/008_normalize_identity.py 1970-01-01 00:00:00 +0000
+++ keystone/common/sql/migrate_repo/versions/008_normalize_identity.py 2013-01-25 16:27:23 +0000
@@ -0,0 +1,58 @@
1# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Copyright 2012 OpenStack LLC
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
17
18from sqlalchemy import Column, MetaData, String, Table, Text, types
19
20
21#this won't work on sqlite. It doesn't support dropping columns
22def downgrade_user_table(meta, migrate_engine):
23 user_table = Table('user', meta, autoload=True)
24 user_table.columns["password"].drop()
25 user_table.columns["enabled"].drop()
26
27
28def downgrade_tenant_table(meta, migrate_engine):
29 tenant_table = Table('tenant', meta, autoload=True)
30 tenant_table.columns["description"].drop()
31 tenant_table.columns["enabled"].drop()
32
33
34def upgrade_user_table(meta, migrate_engine):
35 user_table = Table('user', meta, autoload=True)
36 user_table.create_column(Column("password", String(128)))
37 user_table.create_column(Column("enabled", types.Boolean,
38 default=True))
39
40
41def upgrade_tenant_table(meta, migrate_engine):
42 tenant_table = Table('tenant', meta, autoload=True)
43 tenant_table.create_column(Column("description", Text()))
44 tenant_table.create_column(Column("enabled", types.Boolean))
45
46
47def upgrade(migrate_engine):
48 meta = MetaData()
49 meta.bind = migrate_engine
50 upgrade_user_table(meta, migrate_engine)
51 upgrade_tenant_table(meta, migrate_engine)
52
53
54def downgrade(migrate_engine):
55 meta = MetaData()
56 meta.bind = migrate_engine
57 downgrade_user_table(meta, migrate_engine)
58 downgrade_tenant_table(meta, migrate_engine)
059
=== added file 'keystone/common/sql/migrate_repo/versions/008_sqlite_downgrade.sql'
--- keystone/common/sql/migrate_repo/versions/008_sqlite_downgrade.sql 1970-01-01 00:00:00 +0000
+++ keystone/common/sql/migrate_repo/versions/008_sqlite_downgrade.sql 2013-01-25 16:27:23 +0000
@@ -0,0 +1,5 @@
1-- not supported by sqlite, but should be:
2-- alter TABLE tenant drop column description;
3-- alter TABLE tenant drop column enabled;
4-- The downgrade process will fail without valid SQL in this file
5select count(*) from tenant;
06
=== added file 'keystone/common/sql/migrate_repo/versions/009_normalize_identity_migration.py'
--- keystone/common/sql/migrate_repo/versions/009_normalize_identity_migration.py 1970-01-01 00:00:00 +0000
+++ keystone/common/sql/migrate_repo/versions/009_normalize_identity_migration.py 2013-01-25 16:27:23 +0000
@@ -0,0 +1,145 @@
1# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Copyright 2012 OpenStack LLC
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
17import json
18
19from sqlalchemy import MetaData, Table
20from sqlalchemy.orm import sessionmaker
21
22disabled_values = ['false', 'disabled', 'no', '0']
23
24
25def is_enabled(enabled):
26 #no explicit value means enabled
27 if enabled is None:
28 return 1
29 if enabled is str:
30 if str(enabled).lower() in disabled_values:
31 return 0
32 if enabled:
33 return 1
34 else:
35 return 0
36
37
38def downgrade_user_table(meta, migrate_engine):
39 user_table = Table('user', meta, autoload=True)
40 maker = sessionmaker(bind=migrate_engine)
41 session = maker()
42 user_data = []
43 for a_user in session.query(user_table):
44 id, name, extra, password, enabled = a_user
45 extra_parsed = json.loads(extra)
46 extra_parsed['password'] = password
47 extra_parsed['enabled'] = "%r" % enabled
48 user_data.append((password,
49 json.dumps(extra_parsed),
50 is_enabled(enabled), id))
51 for user in user_data:
52 session.execute("update user "
53 "set extra = '%s' "
54 "where id = '%s'" %
55 user)
56
57 session.commit()
58
59
60def downgrade_tenant_table(meta, migrate_engine):
61 tenant_table = Table('tenant', meta, autoload=True)
62 maker = sessionmaker(bind=migrate_engine)
63 session = maker()
64 tenant_data = []
65 for a_tenant in session.query(tenant_table):
66 id, name, extra, password, enabled = a_tenant
67 extra_parsed = json.loads(extra)
68 extra_parsed['description'] = description
69 extra_parsed['enabled'] = "%r" % enabled
70 tenant_data.append((password,
71 json.dumps(extra_parsed),
72 is_enabled(enabled), id))
73 for tenant in tenant_data:
74 session.execute("update tenant "
75 "set extra = '%s' "
76 "where id = '%s'" %
77 tenant)
78
79 session.commit()
80
81
82def upgrade_user_table(meta, migrate_engine):
83 user_table = Table('user', meta, autoload=True)
84 maker = sessionmaker(bind=migrate_engine)
85 session = maker()
86
87 new_user_data = []
88 for a_user in session.query(user_table):
89 id, name, extra, password, enabled = a_user
90 extra_parsed = json.loads(extra)
91 if 'password' in extra_parsed:
92 password = extra_parsed['password']
93 extra_parsed.pop('password')
94 if 'enabled' in extra_parsed:
95 enabled = extra_parsed['enabled']
96 extra_parsed.pop('enabled')
97 new_user_data.append((password,
98 json.dumps(extra_parsed),
99 is_enabled(enabled), id))
100 for new_user in new_user_data:
101 session.execute("update user "
102 "set password = '%s', extra = '%s', enabled = '%s' "
103 "where id = '%s'" %
104 new_user)
105 session.commit()
106
107
108def upgrade_tenant_table(meta, migrate_engine):
109 tenant_table = Table('tenant', meta, autoload=True)
110
111 maker = sessionmaker(bind=migrate_engine)
112 session = maker()
113 new_tenant_data = []
114 for a_tenant in session.query(tenant_table):
115 id, name, extra, description, enabled = a_tenant
116 extra_parsed = json.loads(extra)
117 if 'description' in extra_parsed:
118 description = extra_parsed['description']
119 extra_parsed.pop('description')
120 if 'enabled' in extra_parsed:
121 enabled = extra_parsed['enabled']
122 extra_parsed.pop('enabled')
123 new_tenant_data.append((description,
124 json.dumps(extra_parsed),
125 is_enabled(enabled), id))
126 for new_tenant in new_tenant_data:
127 session.execute("update tenant "
128 "set description = '%s', extra = '%s', enabled = '%s' "
129 "where id = '%s'" %
130 new_tenant)
131 session.commit()
132
133
134def upgrade(migrate_engine):
135 meta = MetaData()
136 meta.bind = migrate_engine
137 upgrade_user_table(meta, migrate_engine)
138 upgrade_tenant_table(meta, migrate_engine)
139
140
141def downgrade(migrate_engine):
142 meta = MetaData()
143 meta.bind = migrate_engine
144 downgrade_user_table(meta, migrate_engine)
145 downgrade_tenant_table(meta, migrate_engine)
0146
=== added file 'keystone/common/sql/migrate_repo/versions/010_endpoints_v3.py'
--- keystone/common/sql/migrate_repo/versions/010_endpoints_v3.py 1970-01-01 00:00:00 +0000
+++ keystone/common/sql/migrate_repo/versions/010_endpoints_v3.py 2013-01-25 16:27:23 +0000
@@ -0,0 +1,53 @@
1# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Copyright 2012 OpenStack LLC
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
17import sqlalchemy as sql
18
19
20def upgrade(migrate_engine):
21 """Create API-version specific endpoint tables."""
22 meta = sql.MetaData()
23 meta.bind = migrate_engine
24
25 legacy_table = sql.Table('endpoint', meta, autoload=True)
26 legacy_table.rename('endpoint_v2')
27
28 new_table = sql.Table(
29 'endpoint_v3',
30 meta,
31 sql.Column('id', sql.String(64), primary_key=True),
32 sql.Column('legacy_endpoint_id', sql.String(64)),
33 sql.Column('interface', sql.String(8), nullable=False),
34 sql.Column('region', sql.String(255)),
35 sql.Column('service_id',
36 sql.String(64),
37 sql.ForeignKey('service.id'),
38 nullable=False),
39 sql.Column('url', sql.Text(), nullable=False),
40 sql.Column('extra', sql.Text()))
41 new_table.create(migrate_engine, checkfirst=True)
42
43
44def downgrade(migrate_engine):
45 """Replace API-version specific endpoint tables with one based on v2."""
46 meta = sql.MetaData()
47 meta.bind = migrate_engine
48
49 new_table = sql.Table('endpoint_v3', meta, autoload=True)
50 new_table.drop()
51
52 legacy_table = sql.Table('endpoint_v2', meta, autoload=True)
53 legacy_table.rename('endpoint')
054
=== added file 'keystone/common/sql/migrate_repo/versions/011_populate_endpoint_type.py'
--- keystone/common/sql/migrate_repo/versions/011_populate_endpoint_type.py 1970-01-01 00:00:00 +0000
+++ keystone/common/sql/migrate_repo/versions/011_populate_endpoint_type.py 2013-01-25 16:27:23 +0000
@@ -0,0 +1,96 @@
1# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Copyright 2012 OpenStack LLC
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
17import json
18import uuid
19
20import sqlalchemy as sql
21from sqlalchemy import orm
22
23
24ENDPOINT_TYPES = ['public', 'internal', 'admin']
25
26
27def upgrade(migrate_engine):
28 """Split each legacy endpoint into seperate records for each interface."""
29 meta = sql.MetaData()
30 meta.bind = migrate_engine
31
32 legacy_table = sql.Table('endpoint_v2', meta, autoload=True)
33 new_table = sql.Table('endpoint_v3', meta, autoload=True)
34
35 session = orm.sessionmaker(bind=migrate_engine)()
36 for ref in session.query(legacy_table).all():
37 # pull urls out of extra
38 extra = json.loads(ref.extra)
39 urls = dict((i, extra.pop('%surl' % i)) for i in ENDPOINT_TYPES)
40
41 for interface in ENDPOINT_TYPES:
42 endpoint = {
43 'id': uuid.uuid4().hex,
44 'legacy_endpoint_id': ref.id,
45 'interface': interface,
46 'region': ref.region,
47 'service_id': ref.service_id,
48 'url': urls[interface],
49 'extra': json.dumps(extra),
50 }
51 session.execute(
52 'INSERT INTO `%s` (%s) VALUES (%s)' % (
53 new_table.name,
54 ', '.join('%s' % k for k in endpoint.keys()),
55 ', '.join("'%s'" % v for v in endpoint.values())))
56 session.commit()
57
58
59def downgrade(migrate_engine):
60 """Re-create the v2 endpoints table based on v3 endpoints."""
61 meta = sql.MetaData()
62 meta.bind = migrate_engine
63
64 legacy_table = sql.Table('endpoint_v2', meta, autoload=True)
65 new_table = sql.Table('endpoint_v3', meta, autoload=True)
66
67 session = orm.sessionmaker(bind=migrate_engine)()
68 for ref in session.query(new_table).all():
69 extra = json.loads(ref.extra)
70 extra['%surl' % ref.interface] = ref.url
71 endpoint = {
72 'id': ref.legacy_endpoint_id,
73 'region': ref.region,
74 'service_id': ref.service_id,
75 'extra': json.dumps(extra),
76 }
77
78 try:
79 session.execute(
80 'INSERT INTO `%s` (%s) VALUES (%s)' % (
81 legacy_table.name,
82 ', '.join('%s' % k for k in endpoint.keys()),
83 ', '.join("'%s'" % v for v in endpoint.values())))
84 except sql.exc.IntegrityError:
85 q = session.query(legacy_table)
86 q = q.filter_by(id=ref.legacy_endpoint_id)
87 legacy_ref = q.one()
88 extra = json.loads(legacy_ref.extra)
89 extra['%surl' % ref.interface] = ref.url
90
91 session.execute(
92 'UPDATE `%s` SET extra=\'%s\' WHERE id="%s"' % (
93 legacy_table.name,
94 json.dumps(extra),
95 legacy_ref.id))
96 session.commit()
097
=== added file 'keystone/common/sql/migrate_repo/versions/012_drop_legacy_endpoints.py'
--- keystone/common/sql/migrate_repo/versions/012_drop_legacy_endpoints.py 1970-01-01 00:00:00 +0000
+++ keystone/common/sql/migrate_repo/versions/012_drop_legacy_endpoints.py 2013-01-25 16:27:23 +0000
@@ -0,0 +1,50 @@
1# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Copyright 2012 OpenStack LLC
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
17import sqlalchemy as sql
18
19
20def upgrade(migrate_engine):
21 """Replace API-version specific endpoint tables with one based on v3."""
22 meta = sql.MetaData()
23 meta.bind = migrate_engine
24
25 legacy_table = sql.Table('endpoint_v2', meta, autoload=True)
26 legacy_table.drop()
27
28 new_table = sql.Table('endpoint_v3', meta, autoload=True)
29 new_table.rename('endpoint')
30
31
32def downgrade(migrate_engine):
33 """Create API-version specific endpoint tables."""
34 meta = sql.MetaData()
35 meta.bind = migrate_engine
36
37 new_table = sql.Table('endpoint', meta, autoload=True)
38 new_table.rename('endpoint_v3')
39
40 legacy_table = sql.Table(
41 'endpoint_v2',
42 meta,
43 sql.Column('id', sql.String(64), primary_key=True),
44 sql.Column('region', sql.String(255)),
45 sql.Column('service_id',
46 sql.String(64),
47 sql.ForeignKey('service.id'),
48 nullable=False),
49 sql.Column('extra', sql.Text()))
50 legacy_table.create(migrate_engine, checkfirst=True)
051
=== added file 'keystone/common/sql/migrate_repo/versions/013_add_group_tables.py'
--- keystone/common/sql/migrate_repo/versions/013_add_group_tables.py 1970-01-01 00:00:00 +0000
+++ keystone/common/sql/migrate_repo/versions/013_add_group_tables.py 2013-01-25 16:27:23 +0000
@@ -0,0 +1,93 @@
1# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Copyright 2012 OpenStack LLC
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
17import sqlalchemy as sql
18
19
20def upgrade(migrate_engine):
21 meta = sql.MetaData()
22 meta.bind = migrate_engine
23
24 sql.Table('domain', meta, autoload=True)
25 group_table = sql.Table(
26 'group',
27 meta,
28 sql.Column('id', sql.String(64), primary_key=True),
29 sql.Column('domain_id', sql.String(64), sql.ForeignKey('domain.id')),
30 sql.Column('name', sql.String(64), unique=True, nullable=False),
31 sql.Column('description', sql.Text()),
32 sql.Column('extra', sql.Text()))
33 group_table.create(migrate_engine, checkfirst=True)
34
35 sql.Table('user', meta, autoload=True)
36 user_group_membership_table = sql.Table(
37 'user_group_membership',
38 meta,
39 sql.Column(
40 'user_id',
41 sql.String(64),
42 sql.ForeignKey('user.id'),
43 primary_key=True),
44 sql.Column(
45 'group_id',
46 sql.String(64),
47 sql.ForeignKey('group.id'),
48 primary_key=True))
49 user_group_membership_table.create(migrate_engine, checkfirst=True)
50
51 sql.Table('tenant', meta, autoload=True)
52 group_project_metadata_table = sql.Table(
53 'group_project_metadata',
54 meta,
55 sql.Column(
56 'group_id',
57 sql.String(64),
58 sql.ForeignKey('group.id'),
59 primary_key=True),
60 sql.Column(
61 'project_id',
62 sql.String(64),
63 sql.ForeignKey('tenant.id'),
64 primary_key=True),
65 sql.Column('data', sql.Text()))
66 group_project_metadata_table.create(migrate_engine, checkfirst=True)
67
68 group_domain_metadata_table = sql.Table(
69 'group_domain_metadata',
70 meta,
71 sql.Column(
72 'group_id',
73 sql.String(64),
74 sql.ForeignKey('group.id'),
75 primary_key=True),
76 sql.Column(
77 'domain_id',
78 sql.String(64),
79 sql.ForeignKey('domain.id'),
80 primary_key=True),
81 sql.Column('data', sql.Text()))
82 group_domain_metadata_table.create(migrate_engine, checkfirst=True)
83
84
85def downgrade(migrate_engine):
86 meta = sql.MetaData()
87 meta.bind = migrate_engine
88
89 tables = ['user_group_membership', 'group_project_metadata',
90 'group_domain_metadata', 'group']
91 for t in tables:
92 table = sql.Table(t, meta, autoload=True)
93 table.drop(migrate_engine, checkfirst=True)
094
=== modified file 'keystone/common/sql/migration.py'
--- keystone/common/sql/migration.py 2012-06-22 12:27:50 +0000
+++ keystone/common/sql/migration.py 2013-01-25 16:27:23 +0000
@@ -44,7 +44,7 @@
44 try:44 try:
45 version = int(version)45 version = int(version)
46 except ValueError:46 except ValueError:
47 raise Exception('version should be an integer')47 raise Exception(_('version should be an integer'))
4848
49 current_version = db_version()49 current_version = db_version()
50 repo_path = _find_migrate_repo()50 repo_path = _find_migrate_repo()
5151
=== modified file 'keystone/common/sql/nova.py'
--- keystone/common/sql/nova.py 2012-06-22 12:27:50 +0000
+++ keystone/common/sql/nova.py 2013-01-25 16:27:23 +0000
@@ -55,7 +55,7 @@
55 'enabled': True,55 'enabled': True,
56 }56 }
57 tenant_map[tenant['id']] = tenant_dict['id']57 tenant_map[tenant['id']] = tenant_dict['id']
58 LOG.debug('Create tenant %s' % tenant_dict)58 LOG.debug(_('Create tenant %s') % tenant_dict)
59 api.create_tenant(tenant_dict['id'], tenant_dict)59 api.create_tenant(tenant_dict['id'], tenant_dict)
60 return tenant_map60 return tenant_map
6161
@@ -71,7 +71,7 @@
71 'enabled': True,71 'enabled': True,
72 }72 }
73 user_map[user['id']] = user_dict['id']73 user_map[user['id']] = user_dict['id']
74 LOG.debug('Create user %s' % user_dict)74 LOG.debug(_('Create user %s') % user_dict)
75 api.create_user(user_dict['id'], user_dict)75 api.create_user(user_dict['id'], user_dict)
76 return user_map76 return user_map
7777
@@ -80,7 +80,7 @@
80 for membership in memberships:80 for membership in memberships:
81 user_id = user_map[membership['user_id']]81 user_id = user_map[membership['user_id']]
82 tenant_id = tenant_map[membership['tenant_id']]82 tenant_id = tenant_map[membership['tenant_id']]
83 LOG.debug('Add user %s to tenant %s' % (user_id, tenant_id))83 LOG.debug(_('Add user %s to tenant %s') % (user_id, tenant_id))
84 api.add_user_to_tenant(tenant_id, user_id)84 api.add_user_to_tenant(tenant_id, user_id)
8585
8686
@@ -88,14 +88,14 @@
88 role_map = dict((r['name'], r['id']) for r in api.list_roles())88 role_map = dict((r['name'], r['id']) for r in api.list_roles())
89 for role in roles:89 for role in roles:
90 if role in role_map:90 if role in role_map:
91 LOG.debug('Ignoring existing role %s' % role)91 LOG.debug(_('Ignoring existing role %s') % role)
92 continue92 continue
93 role_dict = {93 role_dict = {
94 'id': _generate_uuid(),94 'id': _generate_uuid(),
95 'name': role,95 'name': role,
96 }96 }
97 role_map[role] = role_dict['id']97 role_map[role] = role_dict['id']
98 LOG.debug('Create role %s' % role_dict)98 LOG.debug(_('Create role %s') % role_dict)
99 api.create_role(role_dict['id'], role_dict)99 api.create_role(role_dict['id'], role_dict)
100 return role_map100 return role_map
101101
@@ -105,7 +105,7 @@
105 role_id = role_map[assignment['role']]105 role_id = role_map[assignment['role']]
106 user_id = user_map[assignment['user_id']]106 user_id = user_map[assignment['user_id']]
107 tenant_id = tenant_map[assignment['tenant_id']]107 tenant_id = tenant_map[assignment['tenant_id']]
108 LOG.debug('Assign role %s to user %s on tenant %s' %108 LOG.debug(_('Assign role %s to user %s on tenant %s') %
109 (role_id, user_id, tenant_id))109 (role_id, user_id, tenant_id))
110 api.add_role_to_user_and_tenant(user_id, tenant_id, role_id)110 api.add_role_to_user_and_tenant(user_id, tenant_id, role_id)
111111
@@ -120,6 +120,6 @@
120 'user_id': user_id,120 'user_id': user_id,
121 'tenant_id': tenant_id,121 'tenant_id': tenant_id,
122 }122 }
123 LOG.debug('Creating ec2 cred for user %s and tenant %s' %123 LOG.debug(_('Creating ec2 cred for user %s and tenant %s') %
124 (user_id, tenant_id))124 (user_id, tenant_id))
125 ec2_api.create_credential(None, cred_dict)125 ec2_api.create_credential(None, cred_dict)
126126
=== modified file 'keystone/common/utils.py'
--- keystone/common/utils.py 2012-11-02 13:48:49 +0000
+++ keystone/common/utils.py 2013-01-25 16:27:23 +0000
@@ -31,6 +31,7 @@
3131
32from keystone.common import logging32from keystone.common import logging
33from keystone import config33from keystone import config
34from keystone import exception
3435
3536
36CONF = config.CONF37CONF = config.CONF
@@ -89,8 +90,8 @@
89 credentials['verb'],90 credentials['verb'],
90 credentials['host'],91 credentials['host'],
91 credentials['path'])92 credentials['path'])
92 raise Exception('Unknown Signature Version: %s' %93 raise Exception(_('Unknown Signature Version: %s' %
93 credentials['params']['SignatureVersion'])94 credentials['params']['SignatureVersion']))
9495
95 @staticmethod96 @staticmethod
96 def _get_utf8_value(value):97 def _get_utf8_value(value):
@@ -120,7 +121,7 @@
120121
121 def _calc_signature_2(self, params, verb, server_string, path):122 def _calc_signature_2(self, params, verb, server_string, path):
122 """Generate AWS signature version 2 string."""123 """Generate AWS signature version 2 string."""
123 LOG.debug('using _calc_signature_2')124 LOG.debug(_('using _calc_signature_2'))
124 string_to_sign = '%s\n%s\n%s\n' % (verb, server_string, path)125 string_to_sign = '%s\n%s\n%s\n' % (verb, server_string, path)
125 if self.hmac_256:126 if self.hmac_256:
126 current_hmac = self.hmac_256127 current_hmac = self.hmac_256
@@ -136,22 +137,25 @@
136 val = urllib.quote(val, safe='-_~')137 val = urllib.quote(val, safe='-_~')
137 pairs.append(urllib.quote(key, safe='') + '=' + val)138 pairs.append(urllib.quote(key, safe='') + '=' + val)
138 qs = '&'.join(pairs)139 qs = '&'.join(pairs)
139 LOG.debug('query string: %s', qs)140 LOG.debug(_('query string: %s'), qs)
140 string_to_sign += qs141 string_to_sign += qs
141 LOG.debug('string_to_sign: %s', string_to_sign)142 LOG.debug(_('string_to_sign: %s'), string_to_sign)
142 current_hmac.update(string_to_sign)143 current_hmac.update(string_to_sign)
143 b64 = base64.b64encode(current_hmac.digest())144 b64 = base64.b64encode(current_hmac.digest())
144 LOG.debug('len(b64)=%d', len(b64))145 LOG.debug(_('len(b64)=%d'), len(b64))
145 LOG.debug('base64 encoded digest: %s', b64)146 LOG.debug(_('base64 encoded digest: %s'), b64)
146 return b64147 return b64
147148
148149
149def trunc_password(password):150def trunc_password(password):
150 """Truncate passwords to the MAX_PASSWORD_LENGTH."""151 """Truncate passwords to the MAX_PASSWORD_LENGTH."""
151 if len(password) > MAX_PASSWORD_LENGTH:152 try:
152 return password[:MAX_PASSWORD_LENGTH]153 if len(password) > MAX_PASSWORD_LENGTH:
153 else:154 return password[:MAX_PASSWORD_LENGTH]
154 return password155 else:
156 return password
157 except TypeError:
158 raise exception.ValidationError(attribute='string', target='password')
155159
156160
157def hash_user_password(user):161def hash_user_password(user):
@@ -288,3 +292,22 @@
288 hash_ = hashlib.md5()292 hash_ = hashlib.md5()
289 hash_.update(signed_text)293 hash_.update(signed_text)
290 return hash_.hexdigest()294 return hash_.hexdigest()
295
296
297def setup_remote_pydev_debug():
298 if CONF.pydev_debug_host and CONF.pydev_debug_port:
299 error_msg = ('Error setting up the debug environment. Verify that the'
300 ' option --debug-url has the format <host>:<port> and '
301 'that a debugger processes is listening on that port.')
302
303 try:
304 from pydev import pydevd
305
306 pydevd.settrace(CONF.pydev_debug_host,
307 port=CONF.pydev_debug_port,
308 stdoutToServer=True,
309 stderrToServer=True)
310 return True
311 except:
312 LOG.exception(_(error_msg))
313 raise
291314
=== modified file 'keystone/common/wsgi.py'
--- keystone/common/wsgi.py 2012-11-23 09:01:53 +0000
+++ keystone/common/wsgi.py 2013-01-25 16:27:23 +0000
@@ -70,7 +70,7 @@
7070
71 def start(self, key=None, backlog=128):71 def start(self, key=None, backlog=128):
72 """Run a WSGI server with the given application."""72 """Run a WSGI server with the given application."""
73 LOG.debug('Starting %(arg0)s on %(host)s:%(port)s' %73 LOG.debug(_('Starting %(arg0)s on %(host)s:%(port)s') %
74 {'arg0': sys.argv[0],74 {'arg0': sys.argv[0],
75 'host': self.host,75 'host': self.host,
76 'port': self.port})76 'port': self.port})
@@ -193,7 +193,7 @@
193 arg_dict = req.environ['wsgiorg.routing_args'][1]193 arg_dict = req.environ['wsgiorg.routing_args'][1]
194 action = arg_dict.pop('action')194 action = arg_dict.pop('action')
195 del arg_dict['controller']195 del arg_dict['controller']
196 LOG.debug('arg_dict: %s', arg_dict)196 LOG.debug(_('arg_dict: %s'), arg_dict)
197197
198 # allow middleware up the stack to provide context & params198 # allow middleware up the stack to provide context & params
199 context = req.environ.get(CONTEXT_ENV, {})199 context = req.environ.get(CONTEXT_ENV, {})
@@ -214,7 +214,7 @@
214 try:214 try:
215 result = method(context, **params)215 result = method(context, **params)
216 except exception.Unauthorized as e:216 except exception.Unauthorized as e:
217 LOG.warning("Authorization failed. %s from %s"217 LOG.warning(_("Authorization failed. %s from %s")
218 % (e, req.environ['REMOTE_ADDR']))218 % (e, req.environ['REMOTE_ADDR']))
219 return render_exception(e)219 return render_exception(e)
220 except exception.Error as e:220 except exception.Error as e:
@@ -427,7 +427,7 @@
427 match = req.environ['wsgiorg.routing_args'][1]427 match = req.environ['wsgiorg.routing_args'][1]
428 if not match:428 if not match:
429 return render_exception(429 return render_exception(
430 exception.NotFound(message='The resource could not be found.'))430 exception.NotFound(_('The resource could not be found.')))
431 app = match['controller']431 app = match['controller']
432 return app432 return app
433433
434434
=== modified file 'keystone/config.py'
--- keystone/config.py 2012-11-23 09:01:53 +0000
+++ keystone/config.py 2013-01-25 16:27:23 +0000
@@ -41,8 +41,8 @@
41 logging.config.fileConfig(conf.log_config)41 logging.config.fileConfig(conf.log_config)
42 return42 return
43 else:43 else:
44 raise RuntimeError('Unable to locate specified logging '44 raise RuntimeError(_('Unable to locate specified logging '
45 'config file: %s' % conf.log_config)45 'config file: %s') % conf.log_config)
4646
47 root_logger = logging.root47 root_logger = logging.root
48 if conf.debug:48 if conf.debug:
@@ -122,6 +122,12 @@
122 group = kw.pop('group', None)122 group = kw.pop('group', None)
123 return conf.register_cli_opt(cfg.IntOpt(*args, **kw), group=group)123 return conf.register_cli_opt(cfg.IntOpt(*args, **kw), group=group)
124124
125
126register_cli_bool('standard-threads', default=False)
127
128register_cli_str('pydev-debug-host', default=None)
129register_cli_int('pydev-debug-port', default=None)
130
125register_str('admin_token', default='ADMIN')131register_str('admin_token', default='ADMIN')
126register_str('bind_host', default='0.0.0.0')132register_str('bind_host', default='0.0.0.0')
127register_str('compute_port', default=8774)133register_str('compute_port', default=8774)
@@ -129,7 +135,6 @@
129register_str('public_port', default=5000)135register_str('public_port', default=5000)
130register_str('onready')136register_str('onready')
131register_str('auth_admin_prefix', default='')137register_str('auth_admin_prefix', default='')
132register_bool('standard-threads', default=False)
133register_str('policy_file', default='policy.json')138register_str('policy_file', default='policy.json')
134register_str('policy_default_rule', default=None)139register_str('policy_default_rule', default=None)
135140
@@ -221,6 +226,17 @@
221register_bool('role_allow_update', group='ldap', default=True)226register_bool('role_allow_update', group='ldap', default=True)
222register_bool('role_allow_delete', group='ldap', default=True)227register_bool('role_allow_delete', group='ldap', default=True)
223228
229register_str('group_tree_dn', group='ldap', default=None)
230register_str('group_filter', group='ldap', default=None)
231register_str('group_objectclass', group='ldap', default='groupOfNames')
232register_str('group_id_attribute', group='ldap', default='cn')
233register_str('group_name_attribute', group='ldap', default='ou')
234register_str('group_member_attribute', group='ldap', default='member')
235register_str('group_desc_attribute', group='ldap', default='desc')
236register_list('group_attribute_ignore', group='ldap', default='')
237register_bool('group_allow_create', group='ldap', default=True)
238register_bool('group_allow_update', group='ldap', default=True)
239register_bool('group_allow_delete', group='ldap', default=True)
224#pam240#pam
225register_str('url', group='pam', default=None)241register_str('url', group='pam', default=None)
226register_str('userid', group='pam', default=None)242register_str('userid', group='pam', default=None)
227243
=== modified file 'keystone/contrib/admin_crud/core.py'
--- keystone/contrib/admin_crud/core.py 2012-07-06 10:37:01 +0000
+++ keystone/contrib/admin_crud/core.py 2013-01-25 16:27:23 +0000
@@ -13,7 +13,6 @@
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations14# License for the specific language governing permissions and limitations
15# under the License.15# under the License.
16
17from keystone import catalog16from keystone import catalog
18from keystone.common import wsgi17from keystone.common import wsgi
19from keystone import identity18from keystone import identity
@@ -27,11 +26,11 @@
27 """26 """
2827
29 def add_routes(self, mapper):28 def add_routes(self, mapper):
30 tenant_controller = identity.TenantController()29 tenant_controller = identity.controllers.Tenant()
31 user_controller = identity.UserController()30 user_controller = identity.controllers.User()
32 role_controller = identity.RoleController()31 role_controller = identity.controllers.Role()
33 service_controller = catalog.ServiceController()32 service_controller = catalog.controllers.Service()
34 endpoint_controller = catalog.EndpointController()33 endpoint_controller = catalog.controllers.Endpoint()
3534
36 # Tenant Operations35 # Tenant Operations
37 mapper.connect(36 mapper.connect(
3837
=== modified file 'keystone/contrib/ec2/core.py'
--- keystone/contrib/ec2/core.py 2012-11-23 09:01:53 +0000
+++ keystone/contrib/ec2/core.py 2013-01-25 16:27:23 +0000
@@ -36,21 +36,20 @@
3636
37import uuid37import uuid
3838
39from keystone import catalog39from keystone.common import controller
40from keystone.common import dependency
40from keystone.common import manager41from keystone.common import manager
41from keystone.common import utils42from keystone.common import utils
42from keystone.common import wsgi43from keystone.common import wsgi
43from keystone import config44from keystone import config
44from keystone import exception45from keystone import exception
45from keystone import identity
46from keystone import policy
47from keystone import service
48from keystone import token46from keystone import token
4947
5048
51CONF = config.CONF49CONF = config.CONF
5250
5351
52@dependency.provider('ec2_api')
54class Manager(manager.Manager):53class Manager(manager.Manager):
55 """Default pivot point for the EC2 Credentials backend.54 """Default pivot point for the EC2 Credentials backend.
5655
@@ -96,15 +95,8 @@
96 conditions=dict(method=['DELETE']))95 conditions=dict(method=['DELETE']))
9796
9897
99class Ec2Controller(wsgi.Application):98@dependency.requires('catalog_api', 'ec2_api')
100 def __init__(self):99class Ec2Controller(controller.V2Controller):
101 self.catalog_api = catalog.Manager()
102 self.identity_api = identity.Manager()
103 self.token_api = token.Manager()
104 self.policy_api = policy.Manager()
105 self.ec2_api = Manager()
106 super(Ec2Controller, self).__init__()
107
108 def check_signature(self, creds_ref, credentials):100 def check_signature(self, creds_ref, credentials):
109 signer = utils.Ec2Signer(creds_ref['secret'])101 signer = utils.Ec2Signer(creds_ref['secret'])
110 signature = signer.generate(credentials)102 signature = signer.generate(credentials)
@@ -190,12 +182,10 @@
190 tenant=tenant_ref,182 tenant=tenant_ref,
191 metadata=metadata_ref))183 metadata=metadata_ref))
192184
193 # TODO(termie): make this a util function or something
194 # TODO(termie): i don't think the ec2 middleware currently expects a185 # TODO(termie): i don't think the ec2 middleware currently expects a
195 # full return, but it contains a note saying that it186 # full return, but it contains a note saying that it
196 # would be better to expect a full return187 # would be better to expect a full return
197 token_controller = service.TokenController()188 return token.controllers.Auth.format_authenticate(
198 return token_controller._format_authenticate(
199 token_ref, roles_ref, catalog_ref)189 token_ref, roles_ref, catalog_ref)
200190
201 def create_credential(self, context, user_id, tenant_id):191 def create_credential(self, context, user_id, tenant_id):
202192
=== modified file 'keystone/contrib/user_crud/core.py'
--- keystone/contrib/user_crud/core.py 2012-11-23 09:01:53 +0000
+++ keystone/contrib/user_crud/core.py 2013-01-25 16:27:23 +0000
@@ -20,20 +20,13 @@
20from keystone import exception20from keystone import exception
21from keystone.common import logging21from keystone.common import logging
22from keystone.common import wsgi22from keystone.common import wsgi
23from keystone.identity import Manager as IdentityManager23from keystone import identity
24from keystone.identity import UserController as UserManager
25from keystone.token import Manager as TokenManager
2624
2725
28LOG = logging.getLogger(__name__)26LOG = logging.getLogger(__name__)
2927
3028
31class UserController(wsgi.Application):29class UserController(identity.controllers.User):
32 def __init__(self):
33 self.identity_api = IdentityManager()
34 self.token_api = TokenManager()
35 self.user_controller = UserManager()
36
37 def set_user_password(self, context, user_id, user):30 def set_user_password(self, context, user_id, user):
38 token_id = context.get('token_id')31 token_id = context.get('token_id')
39 original_password = user.get('original_password')32 original_password = user.get('original_password')
@@ -63,9 +56,9 @@
6356
64 admin_context = copy.copy(context)57 admin_context = copy.copy(context)
65 admin_context['is_admin'] = True58 admin_context['is_admin'] = True
66 self.user_controller.set_user_password(admin_context,59 super(UserController, self).set_user_password(admin_context,
67 user_id,60 user_id,
68 update_dict)61 update_dict)
6962
70 token_id = uuid.uuid4().hex63 token_id = uuid.uuid4().hex
71 new_token_ref = copy.copy(token_ref)64 new_token_ref = copy.copy(token_ref)
7265
=== added file 'keystone/controllers.py'
--- keystone/controllers.py 1970-01-01 00:00:00 +0000
+++ keystone/controllers.py 2013-01-25 16:27:23 +0000
@@ -0,0 +1,144 @@
1# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Copyright 2012 OpenStack LLC
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
17from keystone.common import wsgi
18from keystone import catalog
19from keystone import exception
20
21
22class Extensions(wsgi.Application):
23 """Base extensions controller to be extended by public and admin API's."""
24
25 def __init__(self, extensions=None):
26 super(Extensions, self).__init__()
27
28 self.extensions = extensions or {}
29
30 def get_extensions_info(self, context):
31 return {'extensions': {'values': self.extensions.values()}}
32
33 def get_extension_info(self, context, extension_alias):
34 try:
35 return {'extension': self.extensions[extension_alias]}
36 except KeyError:
37 raise exception.NotFound(target=extension_alias)
38
39
40class AdminExtensions(Extensions):
41 def __init__(self, *args, **kwargs):
42 super(AdminExtensions, self).__init__(*args, **kwargs)
43
44 # TODO(dolph): Extensions should obviously provide this information
45 # themselves, but hardcoding it here allows us to match
46 # the API spec in the short term with minimal complexity.
47 self.extensions['OS-KSADM'] = {
48 'name': 'Openstack Keystone Admin',
49 'namespace': 'http://docs.openstack.org/identity/api/ext/'
50 'OS-KSADM/v1.0',
51 'alias': 'OS-KSADM',
52 'updated': '2011-08-19T13:25:27-06:00',
53 'description': 'Openstack extensions to Keystone v2.0 API '
54 'enabling Admin Operations.',
55 'links': [
56 {
57 'rel': 'describedby',
58 # TODO(dolph): link needs to be revised after
59 # bug 928059 merges
60 'type': 'text/html',
61 'href': 'https://github.com/openstack/identity-api',
62 }
63 ]
64 }
65
66
67class PublicExtensions(Extensions):
68 pass
69
70
71class Version(wsgi.Application):
72 def __init__(self, version_type):
73 self.catalog_api = catalog.Manager()
74 self.url_key = '%sURL' % version_type
75
76 super(Version, self).__init__()
77
78 def _get_identity_url(self, context):
79 catalog_ref = self.catalog_api.get_catalog(context=context,
80 user_id=None,
81 tenant_id=None)
82 for region, region_ref in catalog_ref.iteritems():
83 for service, service_ref in region_ref.iteritems():
84 if service == 'identity':
85 return service_ref[self.url_key]
86
87 raise exception.NotImplemented()
88
89 def _get_versions_list(self, context):
90 """The list of versions is dependent on the context."""
91 identity_url = self._get_identity_url(context)
92 if not identity_url.endswith('/'):
93 identity_url = identity_url + '/'
94
95 versions = {}
96 versions['v2.0'] = {
97 'id': 'v2.0',
98 'status': 'beta',
99 'updated': '2011-11-19T00:00:00Z',
100 'links': [
101 {
102 'rel': 'self',
103 'href': identity_url,
104 }, {
105 'rel': 'describedby',
106 'type': 'text/html',
107 'href': 'http://docs.openstack.org/api/openstack-'
108 'identity-service/2.0/content/'
109 }, {
110 'rel': 'describedby',
111 'type': 'application/pdf',
112 'href': 'http://docs.openstack.org/api/openstack-'
113 'identity-service/2.0/identity-dev-guide-'
114 '2.0.pdf'
115 }
116 ],
117 'media-types': [
118 {
119 'base': 'application/json',
120 'type': 'application/vnd.openstack.identity-v2.0'
121 '+json'
122 }, {
123 'base': 'application/xml',
124 'type': 'application/vnd.openstack.identity-v2.0'
125 '+xml'
126 }
127 ]
128 }
129
130 return versions
131
132 def get_versions(self, context):
133 versions = self._get_versions_list(context)
134 return wsgi.render_response(status=(300, 'Multiple Choices'), body={
135 'versions': {
136 'values': versions.values()
137 }
138 })
139
140 def get_version(self, context):
141 versions = self._get_versions_list(context)
142 return wsgi.render_response(body={
143 'version': versions['v2.0']
144 })
0145
=== modified file 'keystone/exception.py'
--- keystone/exception.py 2012-11-23 09:01:53 +0000
+++ keystone/exception.py 2013-01-25 16:27:23 +0000
@@ -148,6 +148,10 @@
148 """Could not find user: %(user_id)s"""148 """Could not find user: %(user_id)s"""
149149
150150
151class GroupNotFound(NotFound):
152 """Could not find group: %(group_id)s"""
153
154
151class Conflict(Error):155class Conflict(Error):
152 """Conflict occurred attempting to store %(type)s.156 """Conflict occurred attempting to store %(type)s.
153157
154158
=== modified file 'keystone/identity/__init__.py'
--- keystone/identity/__init__.py 2012-03-16 11:19:40 +0000
+++ keystone/identity/__init__.py 2013-01-25 16:27:23 +0000
@@ -15,3 +15,5 @@
15# under the License.15# under the License.
1616
17from keystone.identity.core import *17from keystone.identity.core import *
18from keystone.identity import controllers
19from keystone.identity import routers
1820
=== modified file 'keystone/identity/backends/kvs.py'
--- keystone/identity/backends/kvs.py 2012-11-23 09:01:53 +0000
+++ keystone/identity/backends/kvs.py 2013-01-25 16:27:23 +0000
@@ -97,9 +97,13 @@
97 def get_user_by_name(self, user_name):97 def get_user_by_name(self, user_name):
98 return identity.filter_user(self._get_user_by_name(user_name))98 return identity.filter_user(self._get_user_by_name(user_name))
9999
100 def get_metadata(self, user_id, tenant_id):100 def get_metadata(self, user_id=None, tenant_id=None,
101 domain_id=None, group_id=None):
101 try:102 try:
102 return self.db.get('metadata-%s-%s' % (tenant_id, user_id))103 if user_id:
104 return self.db.get('metadata-%s-%s' % (tenant_id, user_id))
105 else:
106 return self.db.get('metadata-%s-%s' % (tenant_id, group_id))
103 except exception.NotFound:107 except exception.NotFound:
104 raise exception.MetadataNotFound()108 raise exception.MetadataNotFound()
105109
@@ -199,12 +203,16 @@
199 raise exception.Conflict(type='user', details=msg)203 raise exception.Conflict(type='user', details=msg)
200204
201 user = utils.hash_user_password(user)205 user = utils.hash_user_password(user)
202 self.db.set('user-%s' % user_id, user)206 new_user = user.copy()
203 self.db.set('user_name-%s' % user['name'], user)207
208 new_user.setdefault('groups', [])
209
210 self.db.set('user-%s' % user_id, new_user)
211 self.db.set('user_name-%s' % new_user['name'], new_user)
204 user_list = set(self.db.get('user_list', []))212 user_list = set(self.db.get('user_list', []))
205 user_list.add(user_id)213 user_list.add(user_id)
206 self.db.set('user_list', list(user_list))214 self.db.set('user_list', list(user_list))
207 return identity.filter_user(user)215 return identity.filter_user(new_user)
208216
209 def update_user(self, user_id, user):217 def update_user(self, user_id, user):
210 if 'name' in user:218 if 'name' in user:
@@ -228,6 +236,42 @@
228 self.db.set('user_name-%s' % new_user['name'], new_user)236 self.db.set('user_name-%s' % new_user['name'], new_user)
229 return new_user237 return new_user
230238
239 def add_user_to_group(self, user_id, group_id):
240 self.get_group(group_id)
241 user_ref = self._get_user(user_id)
242 groups = set(user_ref.get('groups', []))
243 groups.add(group_id)
244 self.update_user(user_id, {'groups': list(groups)})
245
246 def check_user_in_group(self, user_id, group_id):
247 self.get_group(group_id)
248 user_ref = self._get_user(user_id)
249 if not group_id in set(user_ref.get('groups', [])):
250 raise exception.NotFound(_('User not found in group'))
251
252 def remove_user_from_group(self, user_id, group_id):
253 self.get_group(group_id)
254 user_ref = self._get_user(user_id)
255 groups = set(user_ref.get('groups', []))
256 try:
257 groups.remove(group_id)
258 except KeyError:
259 raise exception.NotFound(_('User not found in group'))
260 self.update_user(user_id, {'groups': list(groups)})
261
262 def list_users_in_group(self, group_id):
263 self.get_group(group_id)
264 user_keys = filter(lambda x: x.startswith("user-"), self.db.keys())
265 user_refs = [self.db.get(key) for key in user_keys]
266 user_refs_for_group = filter(lambda x: group_id in x['groups'],
267 user_refs)
268 return [identity.filter_user(x) for x in user_refs_for_group]
269
270 def list_groups_for_user(self, user_id):
271 user_ref = self._get_user(user_id)
272 group_ids = user_ref.get('groups', [])
273 return [self.get_group(x) for x in group_ids]
274
231 def delete_user(self, user_id):275 def delete_user(self, user_id):
232 try:276 try:
233 old_user = self.db.get('user-%s' % user_id)277 old_user = self.db.get('user-%s' % user_id)
@@ -292,16 +336,21 @@
292 self.db.delete('tenant_name-%s' % old_tenant['name'])336 self.db.delete('tenant_name-%s' % old_tenant['name'])
293 self.db.delete('tenant-%s' % tenant_id)337 self.db.delete('tenant-%s' % tenant_id)
294338
295 def create_metadata(self, user_id, tenant_id, metadata):339 def create_metadata(self, user_id, tenant_id, metadata,
296 self.db.set('metadata-%s-%s' % (tenant_id, user_id), metadata)340 domain_id=None, group_id=None):
297 return metadata341 if user_id:
298342 self.db.set('metadata-%s-%s' % (tenant_id, user_id), metadata)
299 def update_metadata(self, user_id, tenant_id, metadata):343 else:
300 self.db.set('metadata-%s-%s' % (tenant_id, user_id), metadata)344 self.db.set('metadata-%s-%s' % (tenant_id, group_id), metadata)
301 return metadata
302
303 def delete_metadata(self, user_id, tenant_id):
304 self.db.delete('metadata-%s-%s' % (tenant_id, user_id))
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches