Browse Source

Merge redux branch (keystone light)

Change-Id: I2cb5b198a06848f42f919ea49e338443131e263e
changes/70/4170/1
James E. Blair 10 years ago
parent
commit
eef1f0d93a
  1. 28
      .gitignore
  2. 16
      .mailmap
  3. 50
      AUTHORS
  4. 68
      HACKING
  5. 192
      HACKING.rst
  6. 202
      LICENSE
  7. 21
      MANIFEST.in
  8. 275
      README.md
  9. 222
      README.rst
  10. 4
      TODO
  11. 84
      bin/keystone
  12. 69
      bin/keystone-admin
  13. 71
      bin/keystone-all
  14. 70
      bin/keystone-auth
  15. 235
      bin/keystone-control
  16. 42
      bin/keystone-import
  17. 36
      bin/keystone-manage
  18. 16
      bin/sampledata
  19. 96
      doc/Makefile
  20. 38
      doc/README.rst
  21. 9495
      doc/design/flow_diagram.pdf
  22. BIN
      doc/design/flow_diagram.png
  23. 87
      doc/design/flow_diagram.sdx
  24. BIN
      doc/design/tenants.pdf
  25. 8183
      doc/design/use_case_1.pdf
  26. BIN
      doc/design/use_case_1.png
  27. 83
      doc/design/use_case_1.sdx
  28. 6006
      doc/design/use_case_2.pdf
  29. BIN
      doc/design/use_case_2.png
  30. 76
      doc/design/use_case_2.sdx
  31. 7995
      doc/design/use_case_3.pdf
  32. BIN
      doc/design/use_case_3.png
  33. 80
      doc/design/use_case_3.sdx
  34. 76
      doc/generate_autodoc_index.py
  35. 97
      doc/source/architecture.rst
  36. 100
      doc/source/configuration.rst
  37. 333
      doc/source/configuringservices.rst
  38. 135
      doc/source/developing.rst
  39. 158
      doc/source/images/305.svg
  40. 135
      doc/source/images/both.svg
  41. 52
      doc/source/images/graphs_delegate_accept.svg
  42. 30
      doc/source/images/graphs_separate.svg
  43. 51
      doc/source/images/graphs_standard_accept.svg
  44. 39
      doc/source/images/graphs_standard_reject.svg
  45. 24
      doc/source/images/graphs_together.svg
  46. 215
      doc/source/images/layouts.svg
  47. 237
      doc/source/images/mapper.svg
  48. 238
      doc/source/images/proxyAuth.svg
  49. 112
      doc/source/keystone.conf.rst
  50. 87
      doc/source/man/keystone-admin.rst
  51. 87
      doc/source/man/keystone-auth.rst
  52. 101
      doc/source/man/keystone-control.rst
  53. 86
      doc/source/man/keystone-import.rst
  54. 192
      doc/source/man/keystone-manage.rst
  55. 90
      doc/source/man/keystone.rst
  56. 85
      doc/source/man/sampledata.rst
  57. 69
      doc/source/serviceAPI_curl_examples.rst
  58. 77
      doc/source/testing.rst
  59. 28
      doc/source/usingkeystone.rst
  60. 159
      docs/Makefile
  61. 56
      docs/keystone_compat_flows.sdx
  62. 0
      docs/source/_templates/.placeholder
  63. 0
      docs/source/_theme/layout.html
  64. 0
      docs/source/_theme/theme.conf
  65. 55
      docs/source/api_curl_examples.rst
  66. 203
      docs/source/architecture.rst
  67. 26
      docs/source/community.rst
  68. 169
      docs/source/conf.py
  69. 488
      docs/source/configuration.rst
  70. 197
      docs/source/configuringservices.rst
  71. 150
      docs/source/developing.rst
  72. 0
      docs/source/images/authComp.svg
  73. 0
      docs/source/images/graphs_305.svg
  74. 0
      docs/source/images/graphs_authComp.svg
  75. 0
      docs/source/images/graphs_authCompDelegate.svg
  76. 0
      docs/source/images/graphs_both.svg
  77. 0
      docs/source/images/graphs_delegate_forbiden_basic.svg
  78. 0
      docs/source/images/graphs_delegate_forbiden_proxy.svg
  79. 0
      docs/source/images/graphs_delegate_reject_basic.svg
  80. 0
      docs/source/images/graphs_delegate_reject_oauth.svg
  81. 0
      docs/source/images/graphs_delegate_unimplemented.svg
  82. 0
      docs/source/images/graphs_mapper.svg
  83. 0
      docs/source/images/graphs_proxyAuth.svg
  84. 0
      docs/source/images/images_layouts.svg
  85. 81
      docs/source/index.rst
  86. 83
      docs/source/man/keystone-all.rst
  87. 97
      docs/source/man/keystone-manage.rst
  88. 0
      docs/source/middleware_architecture.rst
  89. 143
      docs/source/nova-api-paste.rst
  90. 0
      docs/source/old/backends.rst
  91. 0
      docs/source/old/controllingservers.rst
  92. 0
      docs/source/old/endpoints.rst
  93. 0
      docs/source/old/extensions.rst
  94. 0
      docs/source/old/middleware.rst
  95. 0
      docs/source/old/migration.rst
  96. 0
      docs/source/old/releases.rst
  97. 0
      docs/source/old/services.rst
  98. 0
      docs/source/old/ssl.rst
  99. 84
      docs/source/setup.rst
  100. 0
      docs/source/static/basic.css

28
.gitignore

@ -1,21 +1,17 @@
*.pyc
.cache/
.project
.project/
.pydevproject
.pydevproject/
.settings/
.keystone-venv/
*.swp
vendor
.ksl-venv
.venv
build/
dist/
doc/source/sourcecode
.tox
keystone.egg-info/
*.db
.*.swp
*.log
*.pid
pidfile
*.komodoproject
run_tests.log
.coverage
covhtml
pep8.txt
nosetests.xml
bla.db
docs/build
.DS_Store
docs/source/modules.rst
docs/source/keystone.*

16
.mailmap

@ -1,16 +0,0 @@
<dolph.mathews@rackspace.com> <dolph.mathews@gmail.com>
Edouard Thuleau <edouard1.thuleau@orange.com>
<jeblair@hp.com> <corvus@gnu.org>
<jeblair@hp.com> <james.blair@rackspace.com>
<joon.eo@gmail.com> <john.eo@rackspace.com>
Khaled Hussein <khaled.hussein@gmail.com> KnightHacker <khaled.hussein@rackspace.com>
Khaled Hussein <khaled.hussein@gmail.com> Khaled Hussein <khaled.hussein@rackspace.com>
<rjuvvadi@hcl.com> <ramana@venus.lekha.org>
<rjuvvadi@hcl.com> <rrjuvvadi@gmail.com>
<xtoddx@gmail.com> <todd@rubidine.com>
<github@highbridgellc.com> <gihub@highbridgellc.com>
<github@highbridgellc.com> <ziad.sawalha@rackspace.com>
sirish.bitra <sirish.bitra@gmail.com> sirish bitra <sirish.bitra@gmail.com>
sirish.bitra <sirish.bitra@gmail.com> sirishbitra <sirish.bitra@gmail.com>
sirish.bitra <sirish.bitra@gmail.com> bsirish <sirish.bitra@gmail.com>
sirish.bitra <sirish.bitra@gmail.com> root <root@bsirish.(none)>

50
AUTHORS

@ -1,50 +0,0 @@
Adipudi Praveena <padipudi@padipudi.(none)>
Alex Silva <alex.silva@M1BPAGY.(none)>
Anne Gentle <anne@openstack.org>
Anthony Young <sleepsonthefloor@gmail.com>
Brian Lamar <brian.lamar@gmail.com>
Dan Prince <dan.prince@rackspace.com>
Dolph Mathews <dolph.mathews@gmail.com>
Ed Leafe <ed@leafe.com>
Edouard Thuleau <edouard1.thuleau@orange.com>
Eoghan Glynn <eglynn@redhat.com>
gholt <gholt@brim.net>
Ionuț Arțăriși <iartarisi@suse.cz>
jabdul <abdulkader.j@hcl.com>
James E. Blair <jeblair@hp.com>
Jason Cannavale <jason.cannavale@rackspace.com>
Jay Pipes <jaypipes@gmail.com>
Jenkins <jenkins@review.openstack.org>
Jesse Andrews <anotherjesse@gmail.com>
Joe Savak <joe.savak@rackspace.com>
John Dickinson <me@not.mn>
John Eo <joon.eo@gmail.com>
Jorge L. Williams <jorge.williams@rackspace.com>
Joseph W. Breu <joseph.breu@rackspace.com>
Josh Kearney <josh@jk0.org>
Julien Danjou <julien.danjou@enovance.com>
Justin Shepherd <jshepher@rackspace.com>
Kevin L. Mitchell <kevin.mitchell@rackspace.com>
Khaled Hussein <khaled.hussein@gmail.com>
Kiall Mac Innes <kiall@managedit.ie>
Mark Gius <mgius7096@gmail.com>
Mark McLoughlin <markmc@redhat.com>
Monty Taylor <mordred@inaugust.com>
Pádraig Brady <P@draigBrady.com>
Paul Voccio <paul@substation9.com>
Ramana Juvvadi <rjuvvadi@hcl.com>
Robin Norwood <robin.norwood@gmail.com>
root <root@newapps.(none)>
Sai Krishna <saikrishna1511@gmail.com>
Sirish Bitra <sirish.bitra@gmail.com>
Sony K. Philip <sony@hcleai.com>
termie <github@anarkystic.com>
Thierry Carrez <thierry@openstack.org>
Todd Willey <xtoddx@gmail.com>
Will Kelly <the.william.kelly@gmail.com>
Vishvananda Ishaya <vishvananda@gmail.com>
Yaguang Tang <heut2008@gmail.com>
Yogeshwar Srikrishnan <yoga80@yahoo.com>
Yuriy Taraday <yorik.sar@gmail.com>
Ziad Sawalha <github@highbridgellc.com>
Zhongyue Luo <lzyeval@gmail.com>

68
HACKING

@ -1,68 +0,0 @@
Keystone Style Commandments (pilfered from Nova and added to)
=============================================================
Step 1: Read http://www.python.org/dev/peps/pep-0008/
Step 2: Read http://www.python.org/dev/peps/pep-0008/ again
Step 3: Read on
Imports
-------
- thou shalt not import objects, only modules
- thou shalt not import more than one module per line
- thou shalt not make relative imports
- thou shalt organize your imports according to the following template
::
# vim: tabstop=4 shiftwidth=4 softtabstop=4
{{stdlib imports in human alphabetical order}}
\n
{{OpenStack/Keystone imports in human alphabetical order}}
\n
\n
{{begin your code}}
General
-------
- thou shalt put two newlines twixt toplevel code (funcs, classes, etc)
- thou shalt put one newline twixt methods in classes and anywhere else
- thou shalt not write "except:", use "except Exception:" at the very least
- thou shalt include your name with TODOs as in "TODO(waldo)"
- thou shalt not name anything the same name as a builtin or reserved word
- thou shouldeth comment profusely
- thou shalt not violate causality in our time cone, or else
Human Alphabetical Order Examples
---------------------------------
::
import httplib
import logging
import random
import StringIO
import time
import unittest
import keystone.logic.types.fault as fault
import keystone.db.sqlalchemy.api as db_api
Docstrings
----------
Add them to modules, classes, and functions:
"""Summary of the function, class or method, less than 80 characters.
New paragraph after newline that explains in more detail any general
information about the function, class or method. After this, if defining
parameters and return types use the Sphinx format. After that an extra
newline then close the quotations.
When writing the docstring for a class, an extra line should be placed
after the closing quotations. For more in-depth explanations for these
decisions see http://www.python.org/dev/peps/pep-0257/
:param foo: the foo parameter
:param bar: the bar parameter
:returns: description of the return value
"""

192
HACKING.rst

@ -0,0 +1,192 @@
Keystone Style Commandments
===========================
- Step 1: Read http://www.python.org/dev/peps/pep-0008/
- Step 2: Read http://www.python.org/dev/peps/pep-0008/ again
- Step 3: Read on
General
-------
- Put two newlines between top-level code (funcs, classes, etc)
- Put one newline between methods in classes and anywhere else
- Do not write "except:", use "except Exception:" at the very least
- Include your name with TODOs as in "#TODO(termie)"
- Do not name anything the same name as a built-in or reserved word
TODO vs FIXME
-------------
- TODO(name): implies that something should be done (cleanup, refactoring,
etc), but is expected to be functional.
- FIXME(name): implies that the method/function/etc shouldn't be used until
that code is resolved and bug fixed.
Imports
-------
- Do not import objects, only modules
- Do not import more than one module per line
- Do not make relative imports
- Order your imports by the full module path
- Organize your imports according to the following template
Example::
# vim: tabstop=4 shiftwidth=4 softtabstop=4
{{stdlib imports in human alphabetical order}}
\n
{{third-party lib imports in human alphabetical order}}
\n
{{nova imports in human alphabetical order}}
\n
\n
{{begin your code}}
Human Alphabetical Order Examples
---------------------------------
Example::
import httplib
import logging
import random
import StringIO
import time
import unittest
import eventlet
import webob.exc
import nova.api.ec2
from nova.api import openstack
from nova.auth import users
import nova.flags
from nova.endpoint import cloud
from nova import test
Docstrings
----------
Example::
"""A one line docstring looks like this and ends in a period."""
"""A multiline docstring has a one-line summary, less than 80 characters.
Then a new paragraph after a newline that explains in more detail any
general information about the function, class or method. Example usages
are also great to have here if it is a complex class for function.
When writing the docstring for a class, an extra line should be placed
after the closing quotations. For more in-depth explanations for these
decisions see http://www.python.org/dev/peps/pep-0257/
A docstring ends with an empty line before the closing quotations.
Describe parameters and return values, using the Sphinx format; the
appropriate syntax is as follows.
:param foo: the foo parameter
:param bar: the bar parameter
:type bar: parameter type for 'bar'
:returns: return_type -- description of the return value
:returns: description of the return value
:raises: AttributeError, KeyError
"""
Dictionaries/Lists
------------------
If a dictionary (dict) or list object is longer than 80 characters, its items
should be split with newlines. Embedded iterables should have their items
indented. Additionally, the last item in the dictionary should have a trailing
comma. This increases readability and simplifies future diffs.
Example::
my_dictionary = {
"image": {
"name": "Just a Snapshot",
"size": 2749573,
"properties": {
"user_id": 12,
"arch": "x86_64",
},
"things": [
"thing_one",
"thing_two",
],
"status": "ACTIVE",
},
}
Calling Methods
---------------
Calls to methods 80 characters or longer should format each argument with
newlines. This is not a requirement, but a guideline::
unnecessarily_long_function_name('string one',
'string two',
kwarg1=constants.ACTIVE,
kwarg2=['a', 'b', 'c'])
Rather than constructing parameters inline, it is better to break things up::
list_of_strings = [
'what_a_long_string',
'not as long',
]
dict_of_numbers = {
'one': 1,
'two': 2,
'twenty four': 24,
}
object_one.call_a_method('string three',
'string four',
kwarg1=list_of_strings,
kwarg2=dict_of_numbers)
Internationalization (i18n) Strings
-----------------------------------
In order to support multiple languages, we have a mechanism to support
automatic translations of exception and log strings.
Example::
msg = _("An error occurred")
raise HTTPBadRequest(explanation=msg)
If you have a variable to place within the string, first internationalize the
template string then do the replacement.
Example::
msg = _("Missing parameter: %s") % ("flavor",)
LOG.error(msg)
If you have multiple variables to place in the string, use keyword parameters.
This helps our translators reorder parameters when needed.
Example::
msg = _("The server with id %(s_id)s has no key %(m_key)s")
LOG.error(msg % {"s_id": "1234", "m_key": "imageId"})
Creating Unit Tests
-------------------
For every new feature, unit tests should be created that both test and
(implicitly) document the usage of said feature. If submitting a patch for a
bug that had no unit test, a new passing unit test should be added. If a
submitted bug fix does have a unit test, be sure to add a new one that fails
without the patch and passes with the patch.
For more information on creating unit tests and utilizing the testing
infrastructure in OpenStack Nova, please read nova/testing/README.rst.

202
LICENSE

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

21
MANIFEST.in

@ -1,21 +0,0 @@
include AUTHORS
include HACKING
include LICENSE
include MANIFEST.in
include README.md
include pylintrc
include run_tests.py
include run_tests.sh
include setup.py
graft bin
graft doc
prune doc/source/sourcecode
graft etc
graft examples
graft keystone/content
graft keystone/test/etc
graft tools
recursive-include keystone *.json *.xml *.cfg README
include keystone/backends/ldap/keystone.ldif
include keystone/backends/ldap/keystone.schema
global-exclude *.pyc *.sdx *.log *.db *.swp

275
README.md

@ -1,275 +0,0 @@
# Keystone: OpenStack Identity Service
Keystone is a Python implementation of the [OpenStack](http://www.openstack.org) identity service API.
# Documentation
## For users and sysadmins
Learn how to install, configure, manage, and interact with the OpenStack
Identity Service API at the [OpenStack Documentation](http://docs.openstack.org/) site.
## For contributors
Learn how to setup a development environment and then test, run, and contribute to Keystone at the
[Contributor Documentation](http://keystone.openstack.org/) site.
# Questions/Feedback
Having trouble? We'd like to help!
* Try the documentation first — it's got answers to many common questions.
* Search for information in the archives of the [OpenStack mailing list](http://wiki.openstack.org/MailingLists), or post a question.
* Ask a question in the [#openstack IRC channel](http://wiki.openstack.org/UsingIRC).
* If you notice errors, please [open a bug](https://bugs.launchpad.net/keystone) and let us know! Please only use the bug tracker for criticisms and improvements. For tech support, use the resources above.
# For Contributors
## What's in the box?
### Services
* Keystone - identity store and authentication service
* Auth_Token - WSGI middleware that can be used to handle token auth protocol (WSGI or remote proxy)
* Echo - A sample service that responds by returning call details
### Also included:
* Auth_Basic - Stub for WSGI middleware that will be used to handle basic auth
* Auth_OpenID - Stub for WSGI middleware that will be used to handle openid auth protocol (to be implemented)
* RemoteAuth - WSGI middleware that can be used in services (like Swift, Nova, and Glance) when Auth middleware is running remotely
### Built-In commands:
* bin/keystone - Provides HTTP API for users and administrators
* bin/keystone-admin - Provides HTTP API for administrators
* bin/keystone-service - Provides HTTP API for users
* bin/keystone-manage - Provides command-line interface for managing all aspects of Keystone
## Running Keystone
Starting both Admin and Service API endpoints:
$ ./bin/keystone
Starting the auth server only (exposes the Service API):
$ ./bin/keystone-auth
Starting the admin server only (exposes the Admin API):
$ ./bin/keystone-admin
By default, configuration parameters (such as the IP and port binding for each service) are parsed from `etc/keystone.conf`.
## Configuring Keystone
Keystone gets its configuration from command-line parameters or a `.conf` file. While command line parameters take precedence,
Keystone looks in the following location to find a configuration file:
1. Command line parameter
2. /etc/keystone.conf
3. /etc/keystone/keystone.conf
4. <topdir>/etc/keystone.conf
Additional configuration templates are maintained in `keystone/test/etc/` that may be useful as a reference.
### Editing and Building the API Developer Guide
Users of the Keystone API are often developers making ReSTful API calls to Keystone. The guide to provide them
information is therefore called a `Developer Guide`. Developer in this case is not to be confused with contributors
working on the Keystone codebase itself.
The developer guides are automatically generated from XML and other artifacts that live in the
[OpenStack Manuals project](https://launchpad.net/openstack-manuals).
To build the Developer Guide from source, you need [Maven](http://maven.apache.org/). To build the docs and publish a new PDF:
$ cd to folder with the pom.xml file
$ mvn clean generate-sources && cp target/docbkx/pdf/identitydevguide.pdf ../../keystone/content/identitydevguide.pdf
The output will go into the `target` folder (the source is in `src`). Output generated is PDF and webhelp.
# Additional Information:
## Sample data
A set of sample data can be loaded by running a shell script:
$ ./bin/sampledata
The script calls `keystone-manage` to import the sample data.
After starting keystone or running `keystone-manage` a `keystone.db` sqlite database should be created in the keystone folder,
per the default configuration.
## Demo
To run client demo (with all auth middleware running locally on sample service):
$ ./examples/echo/bin/echod
$ python examples/echo/echo_client.py
## CURL commands
<pre>
# Get an unscoped token
$ curl -d '{"auth": {"passwordCredentials": {"username": "joeuser", "password": "secrete"}}}' -H "Content-type: application/json" http://localhost:5000/v2.0/tokens
# Get a token for a tenant
$ curl -d '{"auth": {"passwordCredentials": {"username": "joeuser", "password": "secrete"}, "tenantName": "customer-x"}}' -H "Content-type: application/json" http://localhost:5000/v2.0/tokens
# Get an admin token
$ curl -d '{"auth": {"passwordCredentials": {"username": "admin", "password": "secrete"}}}' -H "Content-type: application/json" http://localhost:35357/v2.0/tokens
</pre>
## Load Testing
<pre>
# Create post data
$ echo '{"auth": {"passwordCredentials": {"username": "joeuser", "password": "secrete", "tenantName": "customer-x"}}}' > post_data
# Call Apache Bench
$ ab -c 30 -n 1000 -T "application/json" -p post_data http://127.0.0.1:35357/v2.0/tokens
</pre>
## NOVA Integration
Initial support for using keystone as nova's identity component has been started.
# clone projects
bzr clone lp:nova
git clone git://github.com/openstack/keystone.git
# install keystone on the host which runs nova
run "python setup install" to install keystone.
# run nova-api based on the paste config in keystone
nova/bin/nova-api --api_paste_config=keystone/examples/paste/nova-api-paste.ini
Assuming you added the test data using bin/sampledata, you can then use joeuser/secrete
## Swift Integration - Quick Start
1. Install Swift, either from trunk or version 1.4.1 (once it's released) or
higher. Do the standard SAIO install with the included TempAuth to be sure
you have a working system to start with. This step is beyond the scope of
this quick start; see http://swift.openstack.org/development_saio.html for
a Swift development set up guide. Once you have a working Swift install, go
ahead and shut it down for now (the default Swift install uses the same
ports Keystone wants):
$ swift-init all stop
2. Obtain and install a source copy of Keystone:
$ git clone https://github.com/openstack/keystone.git ~/keystone
...
$ cd ~/keystone && sudo python setup.py develop
...
3. Start up the Keystone service:
$ cd ~/keystone/bin && ./keystone
Starting the Legacy Authentication component
Service API listening on 0.0.0.0:5000
Admin API listening on 0.0.0.0:35357
4. In another window, edit the `~/keystone/keystone/test/sampledata.py` file,
find the `swift.publicinternets.com` text and replace it with the URL to
your Swift cluster using the following format (note that we're going to
change Swift to run on port 8888 later):
`http://127.0.0.1:8888/v1/AUTH_%tenant_id%`
5. Create the sample data entries:
$ cd ~/keystone/bin && ./sampledata
...
6. Reconfigure Swift's proxy server to use Keystone instead of TempAuth.
Here's an example `/etc/swift/proxy-server.conf`:
[DEFAULT]
bind_port = 8888
user = <user>
[pipeline:main]
pipeline = catch_errors cache keystone proxy-server
[app:proxy-server]
use = egg:swift#proxy
account_autocreate = true
[filter:keystone]
use = egg:keystone#tokenauth
auth_protocol = http
auth_host = 127.0.0.1
auth_port = 35357
admin_token = 999888777666
delay_auth_decision = 0
service_protocol = http
service_host = 127.0.0.1
service_port = 8100
service_pass = dTpw
[filter:cache]
use = egg:swift#memcache
set log_name = cache
[filter:catch_errors]
use = egg:swift#catch_errors
7. Start Swift back up with the new configuration:
$ swift-init main start
...
8. Use `swift` to check everything works (note: you currently have to create a
container or upload something as your first action to have the account
created; there's a Swift bug to be fixed soon):
$ swift -A http://127.0.0.1:5000/v1.0 -U joeuser -K secrete post container
$ swift -A http://127.0.0.1:5000/v1.0 -U joeuser -K secrete stat -v
StorageURL: http://127.0.0.1:8888/v1/AUTH_1234
Auth Token: 74ce1b05-e839-43b7-bd76-85ef178726c3
Account: AUTH_1234
Containers: 1
Objects: 0
Bytes: 0
Accept-Ranges: bytes
X-Trans-Id: tx25c1a6969d8f4372b63912f411de3c3b
**Note: Keystone currently allows any valid token to do anything with any
account.**
But, it works as a demo!
## LDAP Setup on a Mac
Using macports:
sudo port install openldap
It appears the package `python-ldap` needs to be recompiled to work. So,
download it from: http://pypi.python.org/pypi/python-ldap/2.4.1
After unpacking, edit `setup.cfg` as shown below:
library_dirs = /opt/local/lib
include_dirs = /opt/local/include /usr/include/sasl
Then, run:
python setup.py build
sudo python setup.py install
# Relevant Standards and Technologies
[Overlap of Identity Technologies](https://sites.google.com/site/oauthgoog/Overlap)
Keystone could potentially integrate with:
1. [WebID](http://www.w3.org/2005/Incubator/webid/spec/) (See also [FOAF+SSL](http://www.w3.org/wiki/Foaf+ssl))
2. [OpenID](http://openid.net/) and/or [OpenIDConnect](http://openidconnect.com/)
3. [OAUTH2](http://oauth.net/2/)
4. [SAML](http://saml.xml.org/)

222
README.rst

@ -0,0 +1,222 @@
.. image:: http://term.ie/data/medium_ksl.png
:alt: Keystone
.. toctree::
:maxdepth 2
Keystone is an OpenStack project that provides Identity, Token, Catalog and
Policy services for use specifically by projects in the OpenStack family.
Much of the design is precipitated from the expectation that the auth backends
for most deployments will actually be shims in front of existing user systems.
-----------
Development
-----------
Building the Documentation
--------------------------
The documentation is all generated with Sphinx from within the docs directory.
To generate the full set of HTML documentation:
cd docs
make autodoc
make html
make man
the results are in the docs/build/html and docs/build/man directories
respectively.
------------
The Services
------------
Keystone is organized as a group of services exposed on one or many endpoints.
Many of these services are used in a combined fashion by the frontend, for
example an authenticate call will validate user/tenant credentials with the
Identity service and, upon success, create and return a token with the Token
service.
Identity
--------
The Identity service provides auth credential validation and data about Users,
Tenants and Roles, as well as any associated metadata.
In the basic case all this data is managed by the service, allowing the service
to manage all the CRUD associated with the data.
In other cases, this data is pulled, by varying degrees, from an authoritative
backend service. An example of this would be when backending on LDAP. See
`LDAP Backend` below for more details.
Token
-----
The Token service validates and manages Tokens used for authenticating requests
once a user/tenant's credentials have already been verified.
Catalog
-------
The Catalog service provides an endpoint registry used for endpoint discovery.
Policy
------
The Policy service provides a rule-based authorization engine and the
associated rule management interface.
----------
Data Model
----------
Keystone was designed from the ground up to be amenable to multiple styles of
backends and as such many of the methods and data types will happily accept
more data than they know what to do with and pass them on to a backend.
There are a few main data types:
* **User**: has account credentials, is associated with one or more tenants
* **Tenant**: unit of ownership in openstack, contains one or more users
* **Role**: a first-class piece of metadata associated with many user-tenant pairs.
* **Token**: identifying credential associated with a user or user and tenant
* **Extras**: bucket of key-value metadata associated with a user-tenant pair.
* **Rule**: describes a set of requirements for performing an action.
While the general data model allows a many-to-many relationship between Users
and Tenants and a many-to-one relationship between Extras and User-Tenant pairs,
the actual backend implementations take varying levels of advantage of that
functionality.
KVS Backend
-----------
A simple backend interface meant to be further backended on anything that can
support primary key lookups, the most trivial implementation being an in-memory
dict.
Supports all features of the general data model.
PAM Backend
-----------
Extra simple backend that uses the current system's PAM service to authenticate,
providing a one-to-one relationship between Users and Tenants with the `root`
User also having the 'admin' role.
Templated Backend
-----------------
Largely designed for a common use case around service catalogs in the Keystone
project, a Catalog backend that simply expands pre-configured templates to
provide catalog data.
Example paste.deploy config (uses $ instead of % to avoid ConfigParser's
interpolation)::
[DEFAULT]
catalog.RegionOne.identity.publicURL = http://localhost:$(public_port)s/v2.0
catalog.RegionOne.identity.adminURL = http://localhost:$(public_port)s/v2.0
catalog.RegionOne.identity.internalURL = http://localhost:$(public_port)s/v2.0
catalog.RegionOne.identity.name = 'Identity Service'
----------------
Approach to CRUD
----------------
While it is expected that any "real" deployment at a large company will manage
their users, tenants and other metadata in their existing user systems, a
variety of CRUD operations are provided for the sake of development and testing.
CRUD is treated as an extension or additional feature to the core feature set in
that it is not required that a backend support it.
----------------------------------
Approach to Authorization (Policy)
----------------------------------
Various components in the system require that different actions are allowed
based on whether the user is authorized to perform that action.
For the purposes of Keystone there are only a couple levels of
authorization being checked for:
* Require that the performing user is considered an admin.
* Require that the performing user matches the user being referenced.
Other systems wishing to use the policy engine will require additional styles
of checks and will possibly write completely custom backends. Backends included
in Keystone are:
Trivial True
------------
Allows all actions.
Simple Match
------------
Given a list of matches to check for, simply verify that the credentials
contain the matches. For example::
credentials = {'user_id': 'foo', 'is_admin': 1, 'roles': ['nova:netadmin']}
# An admin only call:
policy_api.can_haz(('is_admin:1',), credentials)
# An admin or owner call:
policy_api.can_haz(('is_admin:1', 'user_id:foo'),
credentials)
# A netadmin call:
policy_api.can_haz(('roles:nova:netadmin',),
credentials)
Credentials are generally built from the user metadata in the 'extras' part
of the Identity API. So, adding a 'role' to the user just means adding the role
to the user metadata.
Capability RBAC
---------------
(Not yet implemented.)
Another approach to authorization can be action-based, with a mapping of roles
to which capabilities are allowed for that role. For example::
credentials = {'user_id': 'foo', 'is_admin': 1, 'roles': ['nova:netadmin']}
# add a policy
policy_api.add_policy('action:nova:add_network', ('roles:nova:netadmin',))
policy_api.can_haz(('action:nova:add_network',), credentials)
In the backend this would look up the policy for 'action:nova:add_network' and
then do what is effectively a 'Simple Match' style match against the creds.
-----------
Still To Do
-----------
* LDAP backend.
* Diablo migration.

4
TODO

@ -0,0 +1,4 @@
- test validate token
- policy tests
- ec2 support

84
bin/keystone

@ -1,84 +0,0 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
""" This is only a convenience script. It starts two endpoints of Keystone; the
first one is a Service API server running on port 5000 (by default), and the
second one is an Admin API server running on port 35357 (by default).
By default, keystone uses bind_host and bind_port to set its litening ports,
but since this script runs two endpoints, it uses the following options:
Setting any of the Admin API values for bind host or port using the
admin_* entries in the config file. Specoific to this script only is the
-a/--admin-port option on the command-line (nothing else supports that).
Setting any of the Service API values for bind host or port using the
service_* entries in the config file.
"""
import optparse
import os
import sys
import keystone.tools.tracer # @UnusedImport # module runs on import
from keystone.common import config
from keystone.config import CONF
import keystone.server
# If ../../keystone/__init__.py exists, add ../ to Python search path, so that
# it will override what happens to be installed in /usr/(local/)lib/python...
POSSIBLE_TOPDIR = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
os.pardir, os.pardir))
if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'keystone', '__init__.py')):
sys.path.insert(0, POSSIBLE_TOPDIR)
def get_options():
# Initialize a parser for our configuration paramaters
# since we have special handling for the -a|--admin-port argument
parser = optparse.OptionParser()
common_group = config.add_common_options(parser)
config.add_log_options(parser)
# Handle a special argument to support starting two endpoints
common_group.add_option(
'-a', '--admin-port', dest="admin_port", metavar="PORT",
help="specifies port for Admin API to listen on (default is 35357)")
# Parse CLI arguments and merge with config
(options, args) = config.parse_options(parser)
return options
def main():
# Get merged config and CLI options and admin-specific settings
options = get_options()
config_file = config.find_config_file(options, sys.argv[1:])
CONF(config_files=[config_file])
# Start services
try:
# Load Service API Server
service = keystone.server.Server(name="Service API",
config_name='keystone-legacy-auth')
service.start(wait=False)
except RuntimeError, e:
sys.exit("ERROR: %s" % e)
try:
# Get admin-specific settings
port = options.get('admin_port', None)
host = options.get('bind_host', None)
# Load Admin API server
admin = keystone.server.Server(name='Admin API', config_name='admin')
admin.start(host=host, port=port, wait=True)
except RuntimeError, e:
sys.exit("ERROR: %s" % e)
finally:
service.stop()
if __name__ == '__main__':
main()

69
bin/keystone-admin

@ -1,69 +0,0 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# Copyright 2011 OpenStack LLC.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Keystone Identity Server - Admin API
"""
import optparse
import os
import sys
# If ../../keystone/__init__.py exists, add ../ to Python search path, so that
# it will override what happens to be installed in /usr/(local/)lib/python...
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
os.pardir,
os.pardir))
if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')):
sys.path.insert(0, possible_topdir)
import keystone.tools.tracer # @UnusedImport # module runs on import
from keystone.common import config
from keystone.config import CONF
import keystone.server
def get_options():
# Initialize a parser for our configuration paramaters
# since we have special handling for the -a|--admin-port argument
parser = optparse.OptionParser()
common_group = config.add_common_options(parser)
config.add_log_options(parser)
# Parse CLI arguments and merge with config
(options, args) = config.parse_options(parser)
return options
def main():
# Get merged config and CLI options and admin-specific settings
options = get_options()
config_file = config.find_config_file(options, sys.argv[1:])
CONF(config_files=[config_file])
try:
# Load Admin API server
admin = keystone.server.Server(name='Admin API', config_name='admin')
admin.start(wait=True)
except RuntimeError, e:
sys.exit("ERROR: %s" % e)
if __name__ == '__main__':
main()

71
bin/keystone-all

@ -0,0 +1,71 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
import greenlet
import logging
import os
import sys
# If ../../keystone/__init__.py exists, add ../ to Python search path, so that
# it will override what happens to be installed in /usr/(local/)lib/python...
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
os.pardir,
os.pardir))
if os.path.exists(os.path.join(possible_topdir,
'keystone-all',
'__init__.py')):
sys.path.insert(0, possible_topdir)
from paste import deploy
from keystone import config
from keystone.common import wsgi
CONF = config.CONF
def create_server(conf, name, port):
app = deploy.loadapp('config:%s' % conf, name=name)
return wsgi.Server(app, port)
def serve(*servers):
for server in servers:
logging.debug("starting server %s on port %s", server.application,
server.port)
server.start()
for server in servers:
try:
server.wait()
except greenlet.GreenletExit:
pass
if __name__ == '__main__':
dev_conf = os.path.join(possible_topdir,
'etc',
'keystone.conf')
config_files = None
if os.path.exists(dev_conf):
config_files = [dev_conf]
CONF(config_files=config_files)
config.setup_logging(CONF)
# Log the options used when starting if we're in debug mode...
if CONF.debug:
CONF.log_opt_values(logging.getLogger(CONF.prog), logging.DEBUG)
options = deploy.appconfig('config:%s' % CONF.config_file[0])
servers = []
servers.append(create_server(CONF.config_file[0],
'admin',
int(options['admin_port'])))
servers.append(create_server(CONF.config_file[0],
'main',
int(options['public_port'])))
serve(*servers)

70
bin/keystone-auth

@ -1,70 +0,0 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# Copyright 2011 OpenStack LLC.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Keystone Identity Server - Service API
"""
import optparse
import os
import sys
# If ../../keystone/__init__.py exists, add ../ to Python search path, so that
# it will override what happens to be installed in /usr/(local/)lib/python...
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
os.pardir,
os.pardir))
if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')):
sys.path.insert(0, possible_topdir)
import keystone.tools.tracer # @UnusedImport # module runs on import
from keystone.common import config
from keystone.config import CONF
import keystone.server
def get_options():
# Initialize a parser for our configuration paramaters
# since we have special handling for the -a|--admin-port argument
parser = optparse.OptionParser()
common_group = config.add_common_options(parser)
config.add_log_options(parser)
# Parse CLI arguments and merge with config
(options, args) = config.parse_options(parser)
return options
def main():
# Get merged config and CLI options and admin-specific settings
options = get_options()
config_file = config.find_config_file(options, sys.argv[1:])
CONF(config_files=[config_file])
try:
# Load Service API server
server = keystone.server.Server(name='Service API',
config_name='keystone-legacy-auth')
server.start(wait=True)
except RuntimeError, e:
sys.exit("ERROR: %s" % e)
if __name__ == '__main__':
main()

235
bin/keystone-control

@ -1,235 +0,0 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 OpenStack, LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Helper script for starting/stopping/reloading Keystone server programs.
Copied from Glance. Thanks for some of the code, Swifties ;)
"""
from __future__ import with_statement
import errno
import gettext
import os
import optparse
import resource
import signal
import sys
import time
# If ../keystone/__init__.py exists, add ../ to Python search path, so that
# it will override what happens to be installed in /usr/(local/)lib/python...
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
os.pardir,
os.pardir))
if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')):
sys.path.insert(0, possible_topdir)
gettext.install('keystone', unicode=1)
import keystone.version
from keystone.common import config
ALL_COMMANDS = ['start', 'stop', 'shutdown', 'restart',
'reload', 'force-reload']
ALL_SERVERS = ['keystone-auth', 'keystone-admin']
GRACEFUL_SHUTDOWN_SERVERS = ['keystone-auth', 'keystone-admin']
MAX_DESCRIPTORS = 32768
MAX_MEMORY = (1024 * 1024 * 1024) * 2 # 2 GB
USAGE = """%prog [options] <SERVER> <COMMAND> [CONFPATH]
Where <SERVER> is one of:
all, auth, admin
And command is one of:
start, stop, shutdown, restart, reload, force-reload
And CONFPATH is the optional configuration file to use."""
def pid_files(server, options):
pid_files = []
if options['pid_file']:
if os.path.exists(os.path.abspath(options['pid_file'])):
pid_files = [os.path.abspath(options['pid_file'])]
else:
if os.path.exists('/var/run/keystone/%s.pid' % server):
pid_files = ['/var/run/keystone/%s.pid' % server]
for pid_file in pid_files:
pid = int(open(pid_file).read().strip())
yield pid_file, pid
def do_start(server, options, args):
server_type = '-'.join(server.split('-')[:-1])
for pid_file, pid in pid_files(server, options):
if os.path.exists('/proc/%s' % pid):
print "%s appears to already be running: %s" % (server, pid_file)
return
else:
print "Removing stale pid file %s" % pid_file
os.unlink(pid_file)
try:
resource.setrlimit(resource.RLIMIT_NOFILE,
(MAX_DESCRIPTORS, MAX_DESCRIPTORS))
resource.setrlimit(resource.RLIMIT_DATA,
(MAX_MEMORY, MAX_MEMORY))
except ValueError:
print "Unable to increase file descriptor limit. Running as non-root?"
os.environ['PYTHON_EGG_CACHE'] = '/tmp'
def write_pid_file(pid_file, pid):
dir, file = os.path.split(pid_file)
if not os.path.exists(dir):
try:
os.makedirs(dir)
except OSError, err:
if err.errno == errno.EACCES:
sys.exit('Unable to create %s. Running as non-root?'
% dir)
fp = open(pid_file, 'w')
fp.write('%d\n' % pid)
fp.close()
def launch(ini_file, pid_file):
args = [server, ini_file]
print 'Starting %s with %s' % (server, ini_file)
pid = os.fork()
if pid == 0:
os.setsid()
with open(os.devnull, 'r+b') as nullfile:
for desc in (0, 1, 2): # close stdio
try:
os.dup2(nullfile.fileno(), desc)
except OSError:
pass
try:
os.execlp('%s' % server, server, ini_file)
except OSError, e:
sys.exit('unable to launch %s. Got error: %s'
% (server, "%s" % e))
sys.exit(0)
else:
write_pid_file(pid_file, pid)
if not options['pid_file']:
pid_file = '/var/run/keystone/%s.pid' % server
else:
pid_file = os.path.abspath(options['pid_file'])
conf_file = config.find_config_file(options, args)
if not conf_file:
sys.exit("Could not find any configuration file to use!")
launch_args = [(conf_file, pid_file)]
# start all servers
for conf_file, pid_file in launch_args:
launch(conf_file, pid_file)
def do_stop(server, options, args, graceful=False):
if graceful and server in GRACEFUL_SHUTDOWN_SERVERS:
sig = signal.SIGHUP
else:
sig = signal.SIGTERM
did_anything = False
pfiles = pid_files(server, options)
for pid_file, pid in pfiles:
did_anything = True
try:
print 'Stopping %s pid: %s signal: %s' % (server, pid, sig)
os.kill(pid, sig)
except OSError:
print "Process %d not running" % pid
try:
os.unlink(pid_file)
except OSError:
pass
for pid_file, pid in pfiles:
for _junk in xrange(150): # 15 seconds
if not os.path.exists('/proc/%s' % pid):
break
time.sleep(0.1)
else:
print 'Waited 15 seconds for pid %s (%s) to die; giving up' % \
(pid, pid_file)
if not did_anything:
print 'No %s running' % server
if __name__ == '__main__':
oparser = optparse.OptionParser(usage=USAGE, version='%%prog %s'
% keystone.version.version())
oparser.add_option('--pid-file', default=None, metavar="PATH",
help="File to use as pid file. Default: "
"/var/run/keystone/$server.pid")
config.add_common_options(oparser)
(options, args) = config.parse_options(oparser)
if len(args) < 2:
oparser.print_usage()
sys.exit(1)
server = args.pop(0).lower()
if server == 'all':
servers = ALL_SERVERS
else:
if not server.startswith('keystone-'):
server = 'keystone-%s' % server
if server not in ALL_SERVERS:
server_list = ", ".join([s.replace('keystone-', '')
for s in ALL_SERVERS])
msg = ("Unknown server '%(server)s' specified. Please specify "
"all, or one of the servers: %(server_list)s" % locals())
sys.exit(msg)
servers = [server]
command = args.pop(0).lower()
if command not in ALL_COMMANDS:
command_list = ", ".join(ALL_COMMANDS)
msg = ("Unknown command %(command)s specified. Please specify a "
"command in this list: %(command_list)s" % locals())
sys.exit(msg)
if command == 'start':
for server in servers:
do_start(server, options, args)
if command == 'stop':
for server in servers:
do_stop(server, options, args)
if command == 'shutdown':
for server in servers:
do_stop(server, options, args, graceful=True)
if command == 'restart':
for server in servers:
do_stop(server, options, args)
for server in servers:
do_start(server, options, args)
if command == 'reload' or command == 'force-reload':
for server in servers:
do_stop(server, options, args, graceful=True)
do_start(server, options, args)

42
bin/keystone-import

@ -1,42 +0,0 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (C) 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This file is to read a export file from Nova that will import users,
# tenants and EC2 credentials
# The file should be in the keystone-manage format
import os
import sys
import shlex
# If ../../keystone/__init__.py exists, add ../ to Python search path, so that
# it will override what happens to be installed in /usr/(local/)lib/python...
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
os.pardir,
os.pardir))
if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')):
sys.path.insert(0, possible_topdir)
import keystone.manage
with open(sys.argv[1], 'r') as line:
try:
keystone.manage.main(shlex.split(line))
except Exception as exc:
# Main prints all of the errors we need
sys.exit(1)

36
bin/keystone-manage

@ -2,35 +2,27 @@
import os
import sys
# If ../../keystone/__init__.py exists, add ../ to Python search path, so that
# it will override what happens to be installed in /usr/(local/)lib/python...
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
os.pardir,
os.pardir))
if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')):
if os.path.exists(os.path.join(possible_topdir,
'keystone',
'__init__.py')):
sys.path.insert(0, possible_topdir)
import keystone.manage
import keystone.manage2
import keystone.tools.tracer # @UnusedImport # module runs on import
from keystone import cli
if __name__ == '__main__':
args = sys.argv[1:]
while True:
if len(args) > 1 and args[0] in keystone.manage.OBJECTS:
# the args look like the old 'subject verb' (e.g. 'user add')
# (this module is pending deprecation)
keystone.manage.main()
break
elif len(args) > 2 and args[0] == '-c':
# Remove -c <config file> and try again
del args[0:2]
elif len(args) > 1 and args[0] == '-d':
# Remove -d and try again
del args[0]
else:
# calls that don't start with a 'subject' go to the new impl
# which uses a 'verb_subject' convention (e.g. 'add_user')
keystone.manage2.main()
break
dev_conf = os.path.join(possible_topdir,
'etc',
'keystone.conf')
config_files = None
if os.path.exists(dev_conf):
config_files = [dev_conf]
cli.main(argv=sys.argv, config_files=config_files)

16
bin/sampledata

@ -1,16 +0,0 @@
#!/usr/bin/env python
import os
import sys
# If ../../keystone/__init__.py exists, add ../ to Python search path, so that
# it will override what happens to be installed in /usr/(local/)lib/python...
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
os.pardir,
os.pardir))
if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')):
sys.path.insert(0, possible_topdir)
import keystone.test.sampledata
if __name__ == '__main__':
keystone.test.sampledata.main()

96
doc/Makefile

@ -1,96 +0,0 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SPHINXSOURCE = source
PAPER =
BUILDDIR = build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SPHINXSOURCE)
.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
.DEFAULT_GOAL = html
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
if [ -f .autogenerated ] ; then \
cat .autogenerated | xargs rm ; \
rm .autogenerated ; \
fi
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/nova.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/nova.qhc"