Merge remote-tracking branch 'docs/master'

This commit is contained in:
Morgan Fainberg 2014-06-19 18:10:24 -07:00
commit f7015de3c6
24 changed files with 2753 additions and 0 deletions

1
docs/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build/

90
docs/Makefile Normal file
View File

@ -0,0 +1,90 @@
# 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
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)/*
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/python-keystoneclient.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/python-keystoneclient.qhc"
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
"run these through (pdf)latex."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."

0
docs/ext/__init__.py Normal file
View File

46
docs/ext/apidoc.py Normal file
View File

@ -0,0 +1,46 @@
# Copyright 2014 OpenStack Foundation
#
# 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.
# NOTE(blk-u): Uncomment the [pbr] section in setup.cfg and remove this
# Sphinx extension when https://launchpad.net/bugs/1260495 is fixed.
import os.path as path
from sphinx import apidoc
# NOTE(blk-u): pbr will run Sphinx multiple times when it generates
# documentation. Once for each builder. To run this extension we use the
# 'builder-inited' hook that fires at the beginning of a Sphinx build.
# We use ``run_already`` to make sure apidocs are only generated once
# even if Sphinx is run multiple times.
run_already = False
def run_apidoc(app):
global run_already
if run_already:
return
run_already = True
package_dir = path.abspath(path.join(app.srcdir, '..', '..',
'keystoneclient'))
source_dir = path.join(app.srcdir, 'api')
apidoc.main(['apidoc', package_dir, '-f',
'-H', 'keystoneclient Modules',
'-o', source_dir])
def setup(app):
app.connect('builder-inited', run_apidoc)

View File

View File

@ -0,0 +1,83 @@
{% extends "basic/layout.html" %}
{% set css_files = css_files + ['_static/tweaks.css'] %}
{% set script_files = script_files + ['_static/jquery.tweet.js'] %}
{%- macro sidebar() %}
{%- if not embedded %}{% if not theme_nosidebar|tobool %}
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
{%- block sidebarlogo %}
{%- if logo %}
<p class="logo"><a href="{{ pathto(master_doc) }}">
<img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
</a></p>
{%- endif %}
{%- endblock %}
{%- block sidebartoc %}
{%- if display_toc %}
<h3><a href="{{ pathto(master_doc) }}">{{ _('Table Of Contents') }}</a></h3>
{{ toc }}
{%- endif %}
{%- endblock %}
{%- block sidebarrel %}
{%- if prev %}
<h4>{{ _('Previous topic') }}</h4>
<p class="topless"><a href="{{ prev.link|e }}"
title="{{ _('previous chapter') }}">{{ prev.title }}</a></p>
{%- endif %}
{%- if next %}
<h4>{{ _('Next topic') }}</h4>
<p class="topless"><a href="{{ next.link|e }}"
title="{{ _('next chapter') }}">{{ next.title }}</a></p>
{%- endif %}
{%- endblock %}
{%- block sidebarsourcelink %}
{%- if show_source and has_source and sourcename %}
<h3>{{ _('This Page') }}</h3>
<ul class="this-page-menu">
<li><a href="{{ pathto('_sources/' + sourcename, true)|e }}"
rel="nofollow">{{ _('Show Source') }}</a></li>
</ul>
{%- endif %}
{%- endblock %}
{%- if customsidebar %}
{% include customsidebar %}
{%- endif %}
{%- block sidebarsearch %}
{%- if pagename != "search" %}
<div id="searchbox" style="display: none">
<h3>{{ _('Quick search') }}</h3>
<form class="search" action="{{ pathto('search') }}" method="get">
<input type="text" name="q" size="18" />
<input type="submit" value="{{ _('Go') }}" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
{{ _('Enter search terms or a module, class or function name.') }}
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
{%- endif %}
{%- endblock %}
</div>
</div>
{%- endif %}{% endif %}
{%- endmacro %}
{% block relbar1 %}{% endblock relbar1 %}
{% block header %}
<div id="header">
<h1 id="logo"><a href="http://www.openstack.org/">OpenStack</a></h1>
<ul id="navigation">
<li><a href="http://www.openstack.org/" title="Go to the Home page" class="link">Home</a></li>
<li><a href="http://www.openstack.org/projects/" title="Go to the OpenStack Projects page">Projects</a></li>
<li><a href="http://www.openstack.org/user-stories/" title="Go to the User Stories page" class="link">User Stories</a></li>
<li><a href="http://www.openstack.org/community/" title="Go to the Community page" class="link">Community</a></li>
<li><a href="http://www.openstack.org/blog/" title="Go to the OpenStack Blog">Blog</a></li>
<li><a href="http://wiki.openstack.org/" title="Go to the OpenStack Wiki">Wiki</a></li>
<li><a href="http://docs.openstack.org/" title="Go to OpenStack Documentation" class="current">Documentation</a></li>
</ul>
</div>
{% endblock %}

View File

@ -0,0 +1,4 @@
[theme]
inherit = basic
stylesheet = nature.css
pygments_style = tango

241
docs/source/conf.py Normal file
View File

@ -0,0 +1,241 @@
# -*- coding: utf-8 -*-
#
# python-keystoneclient documentation build configuration file, created by
# sphinx-quickstart on Sun Dec 6 14:19:25 2009.
#
# This file is execfile()d with the current directory set to its containing
# dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
from __future__ import unicode_literals
import os
import sys
import pbr.version
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__),
'..', '..')))
# NOTE(blk-u): Path for our Sphinx extension, remove when
# https://launchpad.net/bugs/1260495 is fixed.
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__),
'..')))
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.append(os.path.abspath('.'))
# -- General configuration ----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc',
'sphinx.ext.todo',
'sphinx.ext.coverage',
'sphinx.ext.intersphinx',
# NOTE(blk-u): Uncomment the [pbr] section in setup.cfg and
# remove this Sphinx extension when
# https://launchpad.net/bugs/1260495 is fixed.
'ext.apidoc',
]
todo_include_todos = True
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = 'python-keystoneclient'
copyright = 'OpenStack Contributors'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
version_info = pbr.version.VersionInfo('python-keystoneclient')
# The short X.Y version.
version = version_info.version_string()
# The full version, including alpha/beta/rc tags.
release = version_info.release_string()
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of documents that shouldn't be included in the build.
#unused_docs = []
# List of directories, relative to source directory, that shouldn't be searched
# for source files.
exclude_trees = []
# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# Grouping the document tree for man pages.
# List of tuples 'sourcefile', 'target', 'title', 'Authors name', 'manual'
man_pages = [
('man/keystone', 'keystone', 'Client for OpenStack Identity API',
['OpenStack Contributors'], 1),
]
# -- Options for HTML output --------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
html_theme_path = ["."]
html_theme = '_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
git_cmd = "git log --pretty=format:'%ad, commit %h' --date=local -n1"
html_last_updated_fmt = os.popen(git_cmd).read()
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_use_modindex = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = ''
# Output file base name for HTML help builder.
htmlhelp_basename = 'python-keystoneclientdoc'
# -- Options for LaTeX output -------------------------------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual])
# .
latex_documents = [
('index', 'python-keystoneclient.tex',
'python-keystoneclient Documentation',
'Nebula Inc, based on work by Rackspace and Jacob Kaplan-Moss',
'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_use_modindex = True
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'python': ('http://docs.python.org/', None),
'nova': ('http://nova.openstack.org', None),
'swift': ('http://swift.openstack.org', None),
'glance': ('http://glance.openstack.org', None)}

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.27.20101213.0545 (20101213.0545)
-->
<!-- Title: AuthComp Pages: 1 -->
<svg width="510pt" height="118pt"
viewBox="0.00 0.00 510.00 118.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 114)">
<title>AuthComp</title>
<polygon fill="white" stroke="white" points="-4,5 -4,-114 507,-114 507,5 -4,5"/>
<!-- AuthComp -->
<g id="node2" class="node"><title>AuthComp</title>
<polygon fill="#fdefe3" stroke="#c00000" points="292,-65 194,-65 194,-25 292,-25 292,-65"/>
<text text-anchor="middle" x="243" y="-48.4" font-family="Helvetica,sans-Serif" font-size="14.00">Auth</text>
<text text-anchor="middle" x="243" y="-32.4" font-family="Helvetica,sans-Serif" font-size="14.00">Component</text>
</g>
<!-- Reject -->
<!-- AuthComp&#45;&gt;Reject -->
<g id="edge3" class="edge"><title>AuthComp&#45;&gt;Reject</title>
<path fill="none" stroke="black" d="M193.933,-51.2787C157.514,-55.939 108.38,-62.2263 73.8172,-66.649"/>
<polygon fill="black" stroke="black" points="73.0637,-63.2168 63.5888,-67.9578 73.9522,-70.1602 73.0637,-63.2168"/>
<text text-anchor="middle" x="129" y="-97.4" font-family="Times,serif" font-size="14.00">Reject</text>
<text text-anchor="middle" x="129" y="-82.4" font-family="Times,serif" font-size="14.00">Unauthenticated</text>
<text text-anchor="middle" x="129" y="-67.4" font-family="Times,serif" font-size="14.00">Requests</text>
</g>
<!-- Service -->
<g id="node6" class="node"><title>Service</title>
<polygon fill="#d1ebf1" stroke="#1f477d" points="502,-65 408,-65 408,-25 502,-25 502,-65"/>
<text text-anchor="middle" x="455" y="-48.4" font-family="Helvetica,sans-Serif" font-size="14.00">OpenStack</text>
<text text-anchor="middle" x="455" y="-32.4" font-family="Helvetica,sans-Serif" font-size="14.00">Service</text>
</g>
<!-- AuthComp&#45;&gt;Service -->
<g id="edge5" class="edge"><title>AuthComp&#45;&gt;Service</title>
<path fill="none" stroke="black" d="M292.17,-45C323.626,-45 364.563,-45 397.52,-45"/>
<polygon fill="black" stroke="black" points="397.917,-48.5001 407.917,-45 397.917,-41.5001 397.917,-48.5001"/>
<text text-anchor="middle" x="350" y="-77.4" font-family="Times,serif" font-size="14.00">Forward</text>
<text text-anchor="middle" x="350" y="-62.4" font-family="Times,serif" font-size="14.00">Authenticated</text>
<text text-anchor="middle" x="350" y="-47.4" font-family="Times,serif" font-size="14.00">Requests</text>
</g>
<!-- Start -->
<!-- Start&#45;&gt;AuthComp -->
<g id="edge7" class="edge"><title>Start&#45;&gt;AuthComp</title>
<path fill="none" stroke="black" d="M59.1526,-21.4745C90.4482,-25.4792 142.816,-32.1802 183.673,-37.4084"/>
<polygon fill="black" stroke="black" points="183.43,-40.9057 193.793,-38.7034 184.318,-33.9623 183.43,-40.9057"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.27.20101213.0545 (20101213.0545)
-->
<!-- Title: AuthCompDelegate Pages: 1 -->
<svg width="588pt" height="104pt"
viewBox="0.00 0.00 588.00 104.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 100)">
<title>AuthCompDelegate</title>
<polygon fill="white" stroke="white" points="-4,5 -4,-100 585,-100 585,5 -4,5"/>
<!-- AuthComp -->
<g id="node2" class="node"><title>AuthComp</title>
<polygon fill="#fdefe3" stroke="#c00000" points="338,-65 240,-65 240,-25 338,-25 338,-65"/>
<text text-anchor="middle" x="289" y="-48.4" font-family="Helvetica,sans-Serif" font-size="14.00">Auth</text>
<text text-anchor="middle" x="289" y="-32.4" font-family="Helvetica,sans-Serif" font-size="14.00">Component</text>
</g>
<!-- Reject -->
<!-- AuthComp&#45;&gt;Reject -->
<g id="edge3" class="edge"><title>AuthComp&#45;&gt;Reject</title>
<path fill="none" stroke="black" d="M239.6,-50.1899C191.406,-55.2531 118.917,-62.8686 73.5875,-67.6309"/>
<polygon fill="black" stroke="black" points="73.0928,-64.1635 63.5132,-68.6893 73.8242,-71.1252 73.0928,-64.1635"/>
<text text-anchor="middle" x="152" y="-83.4" font-family="Times,serif" font-size="14.00">Reject Requests</text>
<text text-anchor="middle" x="152" y="-68.4" font-family="Times,serif" font-size="14.00">Indicated by the Service</text>
</g>
<!-- Service -->
<g id="node6" class="node"><title>Service</title>
<polygon fill="#d1ebf1" stroke="#1f477d" points="580,-65 486,-65 486,-25 580,-25 580,-65"/>
<text text-anchor="middle" x="533" y="-48.4" font-family="Helvetica,sans-Serif" font-size="14.00">OpenStack</text>
<text text-anchor="middle" x="533" y="-32.4" font-family="Helvetica,sans-Serif" font-size="14.00">Service</text>
</g>
<!-- AuthComp&#45;&gt;Service -->
<g id="edge5" class="edge"><title>AuthComp&#45;&gt;Service</title>
<path fill="none" stroke="black" d="M338.009,-49.0804C344.065,-49.4598 350.172,-49.7828 356,-50 405.743,-51.8535 418.259,-51.9103 468,-50 470.523,-49.9031 473.101,-49.7851 475.704,-49.6504"/>
<polygon fill="black" stroke="black" points="476.03,-53.1374 485.807,-49.0576 475.62,-46.1494 476.03,-53.1374"/>
<text text-anchor="middle" x="412" y="-68.4" font-family="Times,serif" font-size="14.00">Forward Requests</text>
<text text-anchor="middle" x="412" y="-53.4" font-family="Times,serif" font-size="14.00">with Identiy Status</text>
</g>
<!-- Service&#45;&gt;AuthComp -->
<g id="edge7" class="edge"><title>Service&#45;&gt;AuthComp</title>
<path fill="none" stroke="black" d="M495.062,-24.9037C486.397,-21.2187 477.064,-17.9304 468,-16 419.314,-5.63183 404.743,-5.9037 356,-16 349.891,-17.2653 343.655,-19.116 337.566,-21.2803"/>
<polygon fill="black" stroke="black" points="336.234,-18.0426 328.158,-24.9003 338.748,-24.5757 336.234,-18.0426"/>
<text text-anchor="middle" x="412" y="-33.4" font-family="Times,serif" font-size="14.00">Send Response OR</text>
<text text-anchor="middle" x="412" y="-18.4" font-family="Times,serif" font-size="14.00">Reject Message</text>
</g>
<!-- Start -->
<!-- Start&#45;&gt;AuthComp -->
<g id="edge9" class="edge"><title>Start&#45;&gt;AuthComp</title>
<path fill="none" stroke="black" d="M59.0178,-20.8384C99.2135,-25.0613 175.782,-33.1055 229.492,-38.7482"/>
<polygon fill="black" stroke="black" points="229.265,-42.2435 239.576,-39.8076 229.997,-35.2818 229.265,-42.2435"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

42
docs/source/index.rst Normal file
View File

@ -0,0 +1,42 @@
Python bindings to the OpenStack Identity API (Keystone)
========================================================
This is a client for OpenStack Identity API. There's a Python API for
:doc:`Identity API v3 <using-api-v3>` and :doc:`v2 <using-api-v2>` (the
:mod:`keystoneclient` modules), and a command-line script (installed as
:doc:`keystone <man/keystone>`).
Contents:
.. toctree::
:maxdepth: 1
man/keystone
using-sessions
using-api-v2
using-api-v3
middlewarearchitecture
api/modules
Contributing
============
Code is hosted `on GitHub`_. Submit bugs to the Keystone project on
`Launchpad`_. Submit code to the ``openstack/python-keystoneclient`` project
using `Gerrit`_.
.. _on GitHub: https://github.com/openstack/python-keystoneclient
.. _Launchpad: https://launchpad.net/python-keystoneclient
.. _Gerrit: http://wiki.openstack.org/GerritWorkflow
Run tests with ``python setup.py test``.
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@ -0,0 +1,150 @@
========================================
:program:`keystone` command line utility
========================================
.. program:: keystone
.. highlight:: bash
SYNOPSIS
========
:program:`keystone` [options] <command> [command-options]
:program:`keystone help`
:program:`keystone help` <command>
DESCRIPTION
===========
The :program:`keystone` command line utility interacts with services providing
OpenStack Identity API (e.g. Keystone).
To communicate with the API, you will need to be authenticated - and the
:program:`keystone` provides multiple options for this.
While bootstrapping keystone the authentication is accomplished with a
shared secret token and the location of the Identity API endpoint. The
shared secret token is configured in keystone.conf as "admin_token".
You can specify those values on the command line with :option:`--os-token`
and :option:`--os-endpoint`, or set them in environment variables:
.. envvar:: OS_SERVICE_TOKEN
Your keystone administrative token
.. envvar:: OS_SERVICE_ENDPOINT
Your Identity API endpoint
The command line options will override any environment variables set.
If you already have accounts, you can use your OpenStack username and
password. You can do this with the :option:`--os-username`,
:option:`--os-password`.
Keystone allows a user to be associated with one or more projects which are
historically called tenants. To specify the project for which you want to
authorize against, you may optionally specify a :option:`--os-tenant-id` or
:option:`--os-tenant-name`.
Instead of using options, it is easier to just set them as environment
variables:
.. envvar:: OS_USERNAME
Your Keystone username.
.. envvar:: OS_PASSWORD
Your Keystone password.
.. envvar:: OS_TENANT_NAME
Name of Keystone project.
.. envvar:: OS_TENANT_ID
ID of Keystone Tenant.
.. envvar:: OS_AUTH_URL
The OpenStack API server URL.
.. envvar:: OS_IDENTITY_API_VERSION
The OpenStack Identity API version.
.. envvar:: OS_CACERT
The location for the CA truststore (PEM formatted) for this client.
.. envvar:: OS_CERT
The location for the keystore (PEM formatted) containing the public
key of this client. This keystore can also optionally contain the
private key of this client.
.. envvar:: OS_KEY
The location for the keystore (PEM formatted) containing the private
key of this client. This value can be empty if the private key is
included in the OS_CERT file.
For example, in Bash you'd use::
export OS_USERNAME=yourname
export OS_PASSWORD=yadayadayada
export OS_TENANT_NAME=myproject
export OS_AUTH_URL=http(s)://example.com:5000/v2.0/
export OS_IDENTITY_API_VERSION=2.0
export OS_CACERT=/etc/keystone/yourca.pem
export OS_CERT=/etc/keystone/yourpublickey.pem
export OS_KEY=/etc/keystone/yourprivatekey.pem
OPTIONS
=======
To get a list of available commands and options run::
keystone help
To get usage and options of a command::
keystone help <command>
EXAMPLES
========
Get information about endpoint-create command::
keystone help endpoint-create
View endpoints of OpenStack services::
keystone catalog
Create a 'service' project::
keystone tenant-create --name=service
Create service user for nova::
keystone user-create --name=nova \
--tenant_id=<project ID> \
--email=nova@nothing.com
View roles::
keystone role-list
BUGS
====
Keystone client is hosted in Launchpad so you can view current bugs at
https://bugs.launchpad.net/python-keystoneclient/.

View File

@ -0,0 +1,428 @@
..
Copyright 2011-2013 OpenStack Foundation
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.
=======================
Middleware Architecture
=======================
Abstract
========
The Keystone middleware architecture supports a common authentication protocol
in use between the OpenStack projects. By using keystone as a common
authentication and authorization mechanism, the OpenStack project can plug in
to existing authentication and authorization systems in use by existing
environments.
In this document, we describe the architecture and responsibilities of the
authentication middleware which acts as the internal API mechanism for
OpenStack projects based on the WSGI standard.
This documentation describes the implementation in
:class:`keystoneclient.middleware.auth_token`
Specification Overview
======================
'Authentication' is the process of determining that users are who they say they
are. Typically, 'authentication protocols' such as HTTP Basic Auth, Digest
Access, public key, token, etc, are used to verify a user's identity. In this
document, we define an ''authentication component'' as a software module that
implements an authentication protocol for an OpenStack service. OpenStack is
using a token based mechanism to represent authentication and authorization.
At a high level, an authentication middleware component is a proxy that
intercepts HTTP calls from clients and populates HTTP headers in the request
context for other WSGI middleware or applications to use. The general flow
of the middleware processing is:
* clear any existing authorization headers to prevent forgery
* collect the token from the existing HTTP request headers
* validate the token
* if valid, populate additional headers representing the identity that has
been authenticated and authorized
* if invalid, or no token present, reject the request (HTTPUnauthorized)
or pass along a header indicating the request is unauthorized (configurable
in the middleware)
* if the keystone service is unavailable to validate the token, reject
the request with HTTPServiceUnavailable.
.. _authComponent:
Authentication Component
------------------------
Figure 1. Authentication Component
.. image:: images/graphs_authComp.svg
:width: 100%
:height: 180
:alt: An Authentication Component
The middleware may also be configured to operate in a 'delegated mode'.
In this mode, the decision to reject an unauthenticated client is delegated to
the OpenStack service, as illustrated in :ref:`authComponentDelegated`.
Here, requests are forwarded to the OpenStack service with an identity status
message that indicates whether the client's identity has been confirmed or is
indeterminate. It is the OpenStack service that decides whether or not a reject
message should be sent to the client.
.. _authComponentDelegated:
Authentication Component (Delegated Mode)
-----------------------------------------
Figure 2. Authentication Component (Delegated Mode)
.. image:: images/graphs_authCompDelegate.svg
:width: 100%
:height: 180
:alt: An Authentication Component (Delegated Mode)
.. _deployStrategies:
Deployment Strategy
===================
The middleware is intended to be used inline with OpenStack wsgi components,
based on the Oslo WSGI middleware class. It is typically deployed
as a configuration element in a paste configuration pipeline of other
middleware components, with the pipeline terminating in the service
application. The middleware conforms to the python WSGI standard [PEP-333]_.
In initializing the middleware, a configuration item (which acts like a python
dictionary) is passed to the middleware with relevant configuration options.
Configuration
-------------
The middleware is configured within the config file of the main application as
a WSGI component. Example for the auth_token middleware::
[app:myService]
paste.app_factory = myService:app_factory
[pipeline:main]
pipeline = authtoken myService
[filter:authtoken]
paste.filter_factory = keystoneclient.middleware.auth_token:filter_factory
# Prefix to prepend at the beginning of the path (string
# value)
#auth_admin_prefix=
# Host providing the admin Identity API endpoint (string
# value)
auth_host=127.0.0.1
# Port of the admin Identity API endpoint (integer value)
auth_port=35357
# Protocol of the admin Identity API endpoint(http or https)
# (string value)
auth_protocol=https
# Complete public Identity API endpoint (string value)
#auth_uri=<None>
# API version of the admin Identity API endpoint (string
# value)
#auth_version=<None>
# Do not handle authorization requests within the middleware,
# but delegate the authorization decision to downstream WSGI
# components (boolean value)
#delay_auth_decision=false
# Request timeout value for communicating with Identity API
# server. (boolean value)
#http_connect_timeout=<None>
# How many times are we trying to reconnect when communicating
# with Identity API Server. (integer value)
#http_request_max_retries=3
# Single shared secret with the Keystone configuration used
# for bootstrapping a Keystone installation, or otherwise
# bypassing the normal authentication process. (string value)
#admin_token=<None>
# Keystone account username (string value)
#admin_user=<None>
# Keystone account password (string value)
admin_password=SuperSekretPassword
# Keystone service account tenant name to validate user tokens
# (string value)
#admin_tenant_name=admin
# Env key for the swift cache (string value)
#cache=<None>
# Required if Keystone server requires client certificate
# (string value)
#certfile=<None>
# Required if Keystone server requires client certificate
# (string value)
#keyfile=<None>
# A PEM encoded Certificate Authority to use when verifying
# HTTPs connections. Defaults to system CAs. (string value)
#cafile=<None>
# Verify HTTPS connections. (boolean value)
#insecure=false
# Directory used to cache files related to PKI tokens (string
# value)
#signing_dir=<None>
# If defined, the memcache server(s) to use for caching (list
# value)
# Deprecated group/name - [DEFAULT]/memcache_servers
#memcached_servers=<None>
# In order to prevent excessive requests and validations, the
# middleware uses an in-memory cache for the tokens the
# Keystone API returns. This is only valid if memcache_servers
# is defined. Set to -1 to disable caching completely.
# (integer value)
#token_cache_time=300
# Value only used for unit testing (integer value)
#revocation_cache_time=1
# (optional) if defined, indicate whether token data should be
# authenticated or authenticated and encrypted. Acceptable
# values are MAC or ENCRYPT. If MAC, token data is
# authenticated (with HMAC) in the cache. If ENCRYPT, token
# data is encrypted and authenticated in the cache. If the
# value is not one of these options or empty, auth_token will
# raise an exception on initialization. (string value)
#memcache_security_strategy=<None>
# (optional, mandatory if memcache_security_strategy is
# defined) this string is used for key derivation. (string
# value)
#memcache_secret_key=<None>
# (optional) indicate whether to set the X-Service-Catalog
# header. If False, middleware will not ask for service
# catalog on token validation and will not set the X-Service-
# Catalog header. (boolean value)
#include_service_catalog=true
# Used to control the use and type of token binding. Can be
# set to: "disabled" to not check token binding. "permissive"
# (default) to validate binding information if the bind type
# is of a form known to the server and ignore it if not.
# "strict" like "permissive" but if the bind type is unknown
# the token will be rejected. "required" any form of token
# binding is needed to be allowed. Finally the name of a
# binding method that must be present in tokens. (string
# value)
#enforce_token_bind=permissive
For services which have a separate paste-deploy ini file, auth_token middleware
can be alternatively configured in [keystone_authtoken] section in the main
config file. For example in Nova, all middleware parameters can be removed
from api-paste.ini::
[filter:authtoken]
paste.filter_factory = keystoneclient.middleware.auth_token:filter_factory
and set in nova.conf::
[DEFAULT]
...
auth_strategy=keystone
[keystone_authtoken]
auth_host = 127.0.0.1
auth_port = 35357
auth_protocol = http
admin_user = admin
admin_password = SuperSekretPassword
admin_tenant_name = service
# Any of the options that could be set in api-paste.ini can be set here.
Note that middleware parameters in paste config take priority, they must be
removed to use values in [keystone_authtoken] section.
Configuration Options
---------------------
* ``auth_admin_prefix``: Prefix to prepend at the beginning of the path
* ``auth_host``: (required) the host providing the keystone service API endpoint
for validating and requesting tokens
* ``auth_port``: (optional, default `35357`) the port used to validate tokens
* ``auth_protocol``: (optional, default `https`)
* ``auth_uri``: (optional, defaults to
`auth_protocol`://`auth_host`:`auth_port`)
* ``auth_version``: API version of the admin Identity API endpoint
* ``delay_auth_decision``: (optional, default `0`) (off). If on, the middleware
will not reject invalid auth requests, but will delegate that decision to
downstream WSGI components.
* ``http_connect_timeout``: (optional) Request timeout value for communicating
with Identity API server.
* ``http_request_max_retries``: (default 3) How many times are we trying to
reconnect when communicating with Identity API Server.
* ``http_handler``: (optional) Allows to pass in the name of a fake
http_handler callback function used instead of `httplib.HTTPConnection` or
`httplib.HTTPSConnection`. Useful for unit testing where network is not
available.
* ``admin_token``: either this or the following three options are required. If
set, this is a single shared secret with the keystone configuration used to
validate tokens.
* ``admin_user``, ``admin_password``, ``admin_tenant_name``: if ``admin_token``
is not set, or invalid, then admin_user, admin_password, and
admin_tenant_name are defined as a service account which is expected to have
been previously configured in Keystone to validate user tokens.
* ``cache``: (optional) Env key for the swift cache
* ``certfile``: (required, if Keystone server requires client cert)
* ``keyfile``: (required, if Keystone server requires client cert) This can be
the same as the certfile if the certfile includes the private key.
* ``cafile``: (optional, defaults to use system CA bundle) the path to a PEM
encoded CA file/bundle that will be used to verify HTTPS connections.
* ``insecure``: (optional, default `False`) Don't verify HTTPS connections
(overrides `cafile`).
* ``signing_dir``: (optional) Directory used to cache files related to PKI
tokens
* ``memcached_servers``: (optional) If defined, the memcache server(s) to use
for caching
* ``token_cache_time``: (default 300) In order to prevent excessive requests
and validations, the middleware uses an in-memory cache for the tokens the
Keystone API returns. This is only valid if memcache_servers s defined. Set
to -1 to disable caching completely.
* ``memcache_security_strategy``: (optional) if defined, indicate whether token
data should be authenticated or authenticated and encrypted. Acceptable
values are MAC or ENCRYPT. If MAC, token data is authenticated (with HMAC)
in the cache. If ENCRYPT, token data is encrypted and authenticated in the
cache. If the value is not one of these options or empty, auth_token will
raise an exception on initialization.
* ``memcache_secret_key``: (mandatory if memcache_security_strategy is defined)
this string is used for key derivation.
* ``include_service_catalog``: (optional, default `True`) Indicate whether to
set the X-Service-Catalog header. If False, middleware will not ask for
service catalog on token validation and will not set the X-Service-Catalog
header.
* ``enforce_token_bind``: (default ``permissive``) Used to control the use and
type of token binding. Can be set to: "disabled" to not check token binding.
"permissive" (default) to validate binding information if the bind type is of
a form known to the server and ignore it if not. "strict" like "permissive"
but if the bind type is unknown the token will be rejected. "required" any
form of token binding is needed to be allowed. Finally the name of a binding
method that must be present in tokens.
Caching for improved response
-----------------------------
In order to prevent excessive requests and validations, the middleware uses an
in-memory cache for the tokens the keystone API returns. Keep in mind that
invalidated tokens may continue to work if they are still in the token cache,
so token_cache_time is configurable. For larger deployments, the middleware
also supports memcache based caching.
* ``memcached_servers``: (optonal) if defined, the memcache server(s) to use for
cacheing. It will be ignored if Swift MemcacheRing is used instead.
* ``token_cache_time``: (optional, default 300 seconds) Set to -1 to disable
caching completely.
When deploying auth_token middleware with Swift, user may elect
to use Swift MemcacheRing instead of the local Keystone memcache.
The Swift MemcacheRing object is passed in from the request environment
and it defaults to 'swift.cache'. However it could be
different, depending on deployment. To use Swift MemcacheRing, you must
provide the ``cache`` option.
* ``cache``: (optional) if defined, the environment key where the Swift
MemcacheRing object is stored.
Memcached and System Time
=========================
When using `memcached`_ with ``auth_token`` middleware, ensure that the system
time of memcached hosts is set to UTC. Memcached uses the host's system
time in determining whether a key has expired, whereas Keystone sets
key expiry in UTC. The timezone used by Keystone and memcached must
match if key expiry is to behave as expected.
.. _`memcached`: http://memcached.org/
Memcache Protection
===================
When using memcached, we are storing user tokens and token validation
information into the cache as raw data. Which means that anyone who
has access to the memcache servers can read and modify data stored
there. To mitigate this risk, ``auth_token`` middleware provides an
option to authenticate and optionally encrypt the token data stored in
the cache.
* ``memcache_security_strategy``: (optional) if defined, indicate
whether token data should be authenticated or authenticated and
encrypted. Acceptable values are ``MAC`` or ``ENCRYPT``. If ``MAC``,
token data is authenticated (with HMAC) in the cache. If
``ENCRYPT``, token data is encrypted and authenticated in the
cache. If the value is not one of these options or empty,
``auth_token`` will raise an exception on initialization.
* ``memcache_secret_key``: (optional, mandatory if
``memcache_security_strategy`` is defined) this string is used for
key derivation. If ``memcache_security_strategy`` is defined and
``memcache_secret_key`` is absent, ``auth_token`` will raise an
exception on initialization.
Exchanging User Information
===========================
The middleware expects to find a token representing the user with the header
``X-Auth-Token`` or ``X-Storage-Token``. `X-Storage-Token` is supported for
swift/cloud files and for legacy Rackspace use. If the token isn't present and
the middleware is configured to not delegate auth responsibility, it will
respond to the HTTP request with HTTPUnauthorized, returning the header
``WWW-Authenticate`` with the value `Keystone uri='...'` to indicate where to
request a token. The auth_uri returned is configured with the middleware.
The authentication middleware extends the HTTP request with the header
``X-Identity-Status``. If a request is successfully authenticated, the value
is set to `Confirmed`. If the middleware is delegating the auth decision to the
service, then the status is set to `Invalid` if the auth request was
unsuccessful.
Extended the request with additional User Information
-----------------------------------------------------
:py:class:`keystoneclient.middleware.auth_token.AuthProtocol` extends the
request with additional information if the user has been authenticated. See the
"What we add to the request for use by the OpenStack service" section in
:py:mod:`keystoneclient.middleware.auth_token` for the list of fields set by
the auth_token middleware.
References
==========
.. [PEP-333] pep0333 Phillip J Eby. 'Python Web Server Gateway Interface
v1.0.'' http://www.python.org/dev/peps/pep-0333/.

View File

@ -0,0 +1,416 @@
/**
* Sphinx stylesheet -- basic theme
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
/* -- main layout ----------------------------------------------------------- */
div.clearer {
clear: both;
}
/* -- relbar ---------------------------------------------------------------- */
div.related {
width: 100%;
font-size: 90%;
}
div.related h3 {
display: none;
}
div.related ul {
margin: 0;
padding: 0 0 0 10px;
list-style: none;
}
div.related li {
display: inline;
}
div.related li.right {
float: right;
margin-right: 5px;
}
/* -- sidebar --------------------------------------------------------------- */
div.sphinxsidebarwrapper {
padding: 10px 5px 0 10px;
}
div.sphinxsidebar {
float: left;
width: 230px;
margin-left: -100%;
font-size: 90%;
}
div.sphinxsidebar ul {
list-style: none;
}
div.sphinxsidebar ul ul,
div.sphinxsidebar ul.want-points {
margin-left: 20px;
list-style: square;
}
div.sphinxsidebar ul ul {
margin-top: 0;
margin-bottom: 0;
}
div.sphinxsidebar form {
margin-top: 10px;
}
div.sphinxsidebar input {
border: 1px solid #98dbcc;
font-family: sans-serif;
font-size: 1em;
}
img {
border: 0;
}
/* -- search page ----------------------------------------------------------- */
ul.search {
margin: 10px 0 0 20px;
padding: 0;
}
ul.search li {
padding: 5px 0 5px 20px;
background-image: url(file.png);
background-repeat: no-repeat;
background-position: 0 7px;
}
ul.search li a {
font-weight: bold;
}
ul.search li div.context {
color: #888;
margin: 2px 0 0 30px;
text-align: left;
}
ul.keywordmatches li.goodmatch a {
font-weight: bold;
}
/* -- index page ------------------------------------------------------------ */
table.contentstable {
width: 90%;
}
table.contentstable p.biglink {
line-height: 150%;
}
a.biglink {
font-size: 1.3em;
}
span.linkdescr {
font-style: italic;
padding-top: 5px;
font-size: 90%;
}
/* -- general index --------------------------------------------------------- */
table.indextable td {
text-align: left;
vertical-align: top;
}
table.indextable dl, table.indextable dd {
margin-top: 0;
margin-bottom: 0;
}
table.indextable tr.pcap {
height: 10px;
}
table.indextable tr.cap {
margin-top: 10px;
background-color: #f2f2f2;
}
img.toggler {
margin-right: 3px;
margin-top: 3px;
cursor: pointer;
}
/* -- general body styles --------------------------------------------------- */
a.headerlink {
visibility: hidden;
}
h1:hover > a.headerlink,
h2:hover > a.headerlink,
h3:hover > a.headerlink,
h4:hover > a.headerlink,
h5:hover > a.headerlink,
h6:hover > a.headerlink,
dt:hover > a.headerlink {
visibility: visible;
}
div.body p.caption {
text-align: inherit;
}
div.body td {
text-align: left;
}
.field-list ul {
padding-left: 1em;
}
.first {
}
p.rubric {
margin-top: 30px;
font-weight: bold;
}
/* -- sidebars -------------------------------------------------------------- */
div.sidebar {
margin: 0 0 0.5em 1em;
border: 1px solid #ddb;
padding: 7px 7px 0 7px;
background-color: #ffe;
width: 40%;
float: right;
}
p.sidebar-title {
font-weight: bold;
}
/* -- topics ---------------------------------------------------------------- */
div.topic {
border: 1px solid #ccc;
padding: 7px 7px 0 7px;
margin: 10px 0 10px 0;
}
p.topic-title {
font-size: 1.1em;
font-weight: bold;
margin-top: 10px;
}
/* -- admonitions ----------------------------------------------------------- */
div.admonition {
margin-top: 10px;
margin-bottom: 10px;
padding: 7px;
}
div.admonition dt {
font-weight: bold;
}
div.admonition dl {
margin-bottom: 0;
}
p.admonition-title {
margin: 0px 10px 5px 0px;
font-weight: bold;
}
div.body p.centered {
text-align: center;
margin-top: 25px;
}
/* -- tables ---------------------------------------------------------------- */
table.docutils {
border: 0;
border-collapse: collapse;
}
table.docutils td, table.docutils th {
padding: 1px 8px 1px 0;
border-top: 0;
border-left: 0;
border-right: 0;
border-bottom: 1px solid #aaa;
}
table.field-list td, table.field-list th {
border: 0 !important;
}
table.footnote td, table.footnote th {
border: 0 !important;
}
th {
text-align: left;
padding-right: 5px;
}
/* -- other body styles ----------------------------------------------------- */
dl {
margin-bottom: 15px;
}
dd p {
margin-top: 0px;
}
dd ul, dd table {
margin-bottom: 10px;
}
dd {
margin-top: 3px;
margin-bottom: 10px;
margin-left: 30px;
}
dt:target, .highlight {
background-color: #fbe54e;
}
dl.glossary dt {
font-weight: bold;
font-size: 1.1em;
}
.field-list ul {
margin: 0;
padding-left: 1em;
}
.field-list p {
margin: 0;
}
.refcount {
color: #060;
}
.optional {
font-size: 1.3em;
}
.versionmodified {
font-style: italic;
}
.system-message {
background-color: #fda;
padding: 5px;
border: 3px solid red;
}
.footnote:target {
background-color: #ffa
}
.line-block {
display: block;
margin-top: 1em;
margin-bottom: 1em;
}
.line-block .line-block {
margin-top: 0;
margin-bottom: 0;
margin-left: 1.5em;
}
/* -- code displays --------------------------------------------------------- */
pre {
overflow: auto;
}
td.linenos pre {
padding: 5px 0px;
border: 0;
background-color: transparent;
color: #aaa;
}
table.highlighttable {
margin-left: 0.5em;
}
table.highlighttable td {
padding: 0 0.5em 0 0.5em;
}
tt.descname {
background-color: transparent;
font-weight: bold;
font-size: 1.2em;
}
tt.descclassname {
background-color: transparent;
}
tt.xref, a tt {
background-color: transparent;
font-weight: bold;
}
h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
background-color: transparent;
}
/* -- math display ---------------------------------------------------------- */
img.math {
vertical-align: middle;
}
div.body div.math p {
text-align: center;
}
span.eqno {
float: right;
}
/* -- printout stylesheet --------------------------------------------------- */
@media print {
div.document,
div.documentwrapper,
div.bodywrapper {
margin: 0 !important;
width: 100%;
}
div.sphinxsidebar,
div.related,
div.footer,
#top-link {
display: none;
}
}

View File

@ -0,0 +1,230 @@
/**
* Sphinx stylesheet -- default theme
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
@import url("basic.css");
/* -- page layout ----------------------------------------------------------- */
body {
font-family: sans-serif;
font-size: 100%;
background-color: #11303d;
color: #000;
margin: 0;
padding: 0;
}
div.document {
background-color: #1c4e63;
}
div.documentwrapper {
float: left;
width: 100%;
}
div.bodywrapper {
margin: 0 0 0 230px;
}
div.body {
background-color: #ffffff;
color: #000000;
padding: 0 20px 30px 20px;
}
div.footer {
color: #ffffff;
width: 100%;
padding: 9px 0 9px 0;
text-align: center;
font-size: 75%;
}
div.footer a {
color: #ffffff;
text-decoration: underline;
}
div.related {
background-color: #133f52;
line-height: 30px;
color: #ffffff;
}
div.related a {
color: #ffffff;
}
div.sphinxsidebar {
}
div.sphinxsidebar h3 {
font-family: 'Trebuchet MS', sans-serif;
color: #ffffff;
font-size: 1.4em;
font-weight: normal;
margin: 0;
padding: 0;
}
div.sphinxsidebar h3 a {
color: #ffffff;
}
div.sphinxsidebar h4 {
font-family: 'Trebuchet MS', sans-serif;
color: #ffffff;
font-size: 1.3em;
font-weight: normal;
margin: 5px 0 0 0;
padding: 0;
}
div.sphinxsidebar p {
color: #ffffff;
}
div.sphinxsidebar p.topless {
margin: 5px 10px 10px 10px;
}
div.sphinxsidebar ul {
margin: 10px;
padding: 0;
color: #ffffff;
}
div.sphinxsidebar a {
color: #98dbcc;
}
div.sphinxsidebar input {
border: 1px solid #98dbcc;
font-family: sans-serif;
font-size: 1em;
}
/* -- body styles ----------------------------------------------------------- */
a {
color: #355f7c;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
div.body p, div.body dd, div.body li {
text-align: left;
line-height: 130%;
}
div.body h1,
div.body h2,
div.body h3,
div.body h4,
div.body h5,
div.body h6 {
font-family: 'Trebuchet MS', sans-serif;
background-color: #f2f2f2;
font-weight: normal;
color: #20435c;
border-bottom: 1px solid #ccc;
margin: 20px -20px 10px -20px;
padding: 3px 0 3px 10px;
}
div.body h1 { margin-top: 0; font-size: 200%; }
div.body h2 { font-size: 160%; }
div.body h3 { font-size: 140%; }
div.body h4 { font-size: 120%; }
div.body h5 { font-size: 110%; }
div.body h6 { font-size: 100%; }
a.headerlink {
color: #c60f0f;
font-size: 0.8em;
padding: 0 4px 0 4px;
text-decoration: none;
}
a.headerlink:hover {
background-color: #c60f0f;
color: white;
}
div.body p, div.body dd, div.body li {
text-align: left;
line-height: 130%;
}
div.admonition p.admonition-title + p {
display: inline;
}
div.admonition p {
margin-bottom: 5px;
}
div.admonition pre {
margin-bottom: 5px;
}
div.admonition ul, div.admonition ol {
margin-bottom: 5px;
}
div.note {
background-color: #eee;
border: 1px solid #ccc;
}
div.seealso {
background-color: #ffc;
border: 1px solid #ff6;
}
div.topic {
background-color: #eee;
}
div.warning {
background-color: #ffe4e4;
border: 1px solid #f66;
}
p.admonition-title {
display: inline;
}
p.admonition-title:after {
content: ":";
}
pre {
padding: 5px;
background-color: #eeffcc;
color: #333333;
line-height: 120%;
border: 1px solid #ac9;
border-left: none;
border-right: none;
}
tt {
background-color: #ecf0f3;
padding: 0 1px 0 1px;
font-size: 0.95em;
}
.warning tt {
background: #efc2c2;
}
.note tt {
background: #d6d6d6;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -0,0 +1,154 @@
(function($) {
$.fn.tweet = function(o){
var s = {
username: ["seaofclouds"], // [string] required, unless you want to display our tweets. :) it can be an array, just do ["username1","username2","etc"]
list: null, //[string] optional name of list belonging to username
avatar_size: null, // [integer] height and width of avatar if displayed (48px max)
count: 3, // [integer] how many tweets to display?
intro_text: null, // [string] do you want text BEFORE your your tweets?
outro_text: null, // [string] do you want text AFTER your tweets?
join_text: null, // [string] optional text in between date and tweet, try setting to "auto"
auto_join_text_default: "i said,", // [string] auto text for non verb: "i said" bullocks
auto_join_text_ed: "i", // [string] auto text for past tense: "i" surfed
auto_join_text_ing: "i am", // [string] auto tense for present tense: "i was" surfing
auto_join_text_reply: "i replied to", // [string] auto tense for replies: "i replied to" @someone "with"
auto_join_text_url: "i was looking at", // [string] auto tense for urls: "i was looking at" http:...
loading_text: null, // [string] optional loading text, displayed while tweets load
query: null // [string] optional search query
};
if(o) $.extend(s, o);
$.fn.extend({
linkUrl: function() {
var returning = [];
var regexp = /((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi;
this.each(function() {
returning.push(this.replace(regexp,"<a href=\"$1\">$1</a>"));
});
return $(returning);
},
linkUser: function() {
var returning = [];
var regexp = /[\@]+([A-Za-z0-9-_]+)/gi;
this.each(function() {
returning.push(this.replace(regexp,"<a href=\"http://twitter.com/$1\">@$1</a>"));
});
return $(returning);
},
linkHash: function() {
var returning = [];
var regexp = / [\#]+([A-Za-z0-9-_]+)/gi;
this.each(function() {
returning.push(this.replace(regexp, ' <a href="http://search.twitter.com/search?q=&tag=$1&lang=all&from='+s.username.join("%2BOR%2B")+'">#$1</a>'));
});
return $(returning);
},
capAwesome: function() {
var returning = [];
this.each(function() {
returning.push(this.replace(/\b(awesome)\b/gi, '<span class="awesome">$1</span>'));
});
return $(returning);
},
capEpic: function() {
var returning = [];
this.each(function() {
returning.push(this.replace(/\b(epic)\b/gi, '<span class="epic">$1</span>'));
});
return $(returning);
},
makeHeart: function() {
var returning = [];
this.each(function() {
returning.push(this.replace(/(&lt;)+[3]/gi, "<tt class='heart'>&#x2665;</tt>"));
});
return $(returning);
}
});
function relative_time(time_value) {
var parsed_date = Date.parse(time_value);
var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
var pluralize = function (singular, n) {
return '' + n + ' ' + singular + (n == 1 ? '' : 's');
};
if(delta < 60) {
return 'less than a minute ago';
} else if(delta < (45*60)) {
return 'about ' + pluralize("minute", parseInt(delta / 60)) + ' ago';
} else if(delta < (24*60*60)) {
return 'about ' + pluralize("hour", parseInt(delta / 3600)) + ' ago';
} else {
return 'about ' + pluralize("day", parseInt(delta / 86400)) + ' ago';
}
}
function build_url() {
var proto = ('https:' == document.location.protocol ? 'https:' : 'http:');
if (s.list) {
return proto+"//api.twitter.com/1/"+s.username[0]+"/lists/"+s.list+"/statuses.json?per_page="+s.count+"&callback=?";
} else if (s.query == null && s.username.length == 1) {
return proto+'//twitter.com/status/user_timeline/'+s.username[0]+'.json?count='+s.count+'&callback=?';
} else {
var query = (s.query || 'from:'+s.username.join('%20OR%20from:'));
return proto+'//search.twitter.com/search.json?&q='+query+'&rpp='+s.count+'&callback=?';
}
}
return this.each(function(){
var list = $('<ul class="tweet_list">').appendTo(this);
var intro = '<p class="tweet_intro">'+s.intro_text+'</p>';
var outro = '<p class="tweet_outro">'+s.outro_text+'</p>';
var loading = $('<p class="loading">'+s.loading_text+'</p>');
if(typeof(s.username) == "string"){
s.username = [s.username];
}
if (s.loading_text) $(this).append(loading);
$.getJSON(build_url(), function(data){
if (s.loading_text) loading.remove();
if (s.intro_text) list.before(intro);
$.each((data.results || data), function(i,item){
// auto join text based on verb tense and content
if (s.join_text == "auto") {
if (item.text.match(/^(@([A-Za-z0-9-_]+)) .*/i)) {
var join_text = s.auto_join_text_reply;
} else if (item.text.match(/(^\w+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+) .*/i)) {
var join_text = s.auto_join_text_url;
} else if (item.text.match(/^((\w+ed)|just) .*/im)) {
var join_text = s.auto_join_text_ed;
} else if (item.text.match(/^(\w*ing) .*/i)) {
var join_text = s.auto_join_text_ing;
} else {
var join_text = s.auto_join_text_default;
}
} else {
var join_text = s.join_text;
};
var from_user = item.from_user || item.user.screen_name;
var profile_image_url = item.profile_image_url || item.user.profile_image_url;
var join_template = '<span class="tweet_join"> '+join_text+' </span>';
var join = ((s.join_text) ? join_template : ' ');
var avatar_template = '<a class="tweet_avatar" href="http://twitter.com/'+from_user+'"><img src="'+profile_image_url+'" height="'+s.avatar_size+'" width="'+s.avatar_size+'" alt="'+from_user+'\'s avatar" title="'+from_user+'\'s avatar" border="0"/></a>';
var avatar = (s.avatar_size ? avatar_template : '');
var date = '<a href="http://twitter.com/'+from_user+'/statuses/'+item.id+'" title="view tweet on twitter">'+relative_time(item.created_at)+'</a>';
var text = '<span class="tweet_text">' +$([item.text]).linkUrl().linkUser().linkHash().makeHeart().capAwesome().capEpic()[0]+ '</span>';
// until we create a template option, arrange the items below to alter a tweet's display.
list.append('<li>' + avatar + date + join + text + '</li>');
list.children('li:first').addClass('tweet_first');
list.children('li:odd').addClass('tweet_even');
list.children('li:even').addClass('tweet_odd');
});
if (s.outro_text) list.after(outro);
});
});
};
})(jQuery);

View File

@ -0,0 +1,245 @@
/*
* nature.css_t
* ~~~~~~~~~~~~
*
* Sphinx stylesheet -- nature theme.
*
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
@import url("basic.css");
/* -- page layout ----------------------------------------------------------- */
body {
font-family: Arial, sans-serif;
font-size: 100%;
background-color: #111;
color: #555;
margin: 0;
padding: 0;
}
div.documentwrapper {
float: left;
width: 100%;
}
div.bodywrapper {
margin: 0 0 0 {{ theme_sidebarwidth|toint }}px;
}
hr {
border: 1px solid #B1B4B6;
}
div.document {
background-color: #eee;
}
div.body {
background-color: #ffffff;
color: #3E4349;
padding: 0 30px 30px 30px;
font-size: 0.9em;
}
div.footer {
color: #555;
width: 100%;
padding: 13px 0;
text-align: center;
font-size: 75%;
}
div.footer a {
color: #444;
text-decoration: underline;
}
div.related {
background-color: #6BA81E;
line-height: 32px;
color: #fff;
text-shadow: 0px 1px 0 #444;
font-size: 0.9em;
}
div.related a {
color: #E2F3CC;
}
div.sphinxsidebar {
font-size: 0.75em;
line-height: 1.5em;
}
div.sphinxsidebarwrapper{
padding: 20px 0;
}
div.sphinxsidebar h3,
div.sphinxsidebar h4 {
font-family: Arial, sans-serif;
color: #222;
font-size: 1.2em;
font-weight: normal;
margin: 0;
padding: 5px 10px;
background-color: #ddd;
text-shadow: 1px 1px 0 white
}
div.sphinxsidebar h4{
font-size: 1.1em;
}
div.sphinxsidebar h3 a {
color: #444;
}
div.sphinxsidebar p {
color: #888;
padding: 5px 20px;
}
div.sphinxsidebar p.topless {
}
div.sphinxsidebar ul {
margin: 10px 20px;
padding: 0;
color: #000;
}
div.sphinxsidebar a {
color: #444;
}
div.sphinxsidebar input {
border: 1px solid #ccc;
font-family: sans-serif;
font-size: 1em;
}
div.sphinxsidebar input[type=text]{
margin-left: 20px;
}
/* -- body styles ----------------------------------------------------------- */
a {
color: #005B81;
text-decoration: none;
}
a:hover {
color: #E32E00;
text-decoration: underline;
}
div.body h1,
div.body h2,
div.body h3,
div.body h4,
div.body h5,
div.body h6 {
font-family: Arial, sans-serif;
background-color: #BED4EB;
font-weight: normal;
color: #212224;
margin: 30px 0px 10px 0px;
padding: 5px 0 5px 10px;
text-shadow: 0px 1px 0 white
}
div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; }
div.body h2 { font-size: 150%; background-color: #C8D5E3; }
div.body h3 { font-size: 120%; background-color: #D8DEE3; }
div.body h4 { font-size: 110%; background-color: #D8DEE3; }
div.body h5 { font-size: 100%; background-color: #D8DEE3; }
div.body h6 { font-size: 100%; background-color: #D8DEE3; }
a.headerlink {
color: #c60f0f;
font-size: 0.8em;
padding: 0 4px 0 4px;
text-decoration: none;
}
a.headerlink:hover {
background-color: #c60f0f;
color: white;
}
div.body p, div.body dd, div.body li {
line-height: 1.5em;
}
div.admonition p.admonition-title + p {
display: inline;
}
div.highlight{
background-color: white;
}
div.note {
background-color: #eee;
border: 1px solid #ccc;
}
div.seealso {
background-color: #ffc;
border: 1px solid #ff6;
}
div.topic {
background-color: #eee;
}
div.warning {
background-color: #ffe4e4;
border: 1px solid #f66;
}
p.admonition-title {
display: inline;
}
p.admonition-title:after {
content: ":";
}
pre {
padding: 10px;
background-color: White;
color: #222;
line-height: 1.2em;
border: 1px solid #C6C9CB;
font-size: 1.1em;
margin: 1.5em 0 1.5em 0;
-webkit-box-shadow: 1px 1px 1px #d8d8d8;
-moz-box-shadow: 1px 1px 1px #d8d8d8;
}
tt {
background-color: #ecf0f3;
color: #222;
/* padding: 1px 2px; */
font-size: 1.1em;
font-family: monospace;
}
.viewcode-back {
font-family: Arial, sans-serif;
}
div.viewcode-block:target {
background-color: #f4debf;
border-top: 1px solid #ac9;
border-bottom: 1px solid #ac9;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -0,0 +1,94 @@
body {
background: #fff url(../_static/header_bg.jpg) top left no-repeat;
}
#header {
width: 950px;
margin: 0 auto;
height: 102px;
}
#header h1#logo {
background: url(../_static/openstack_logo.png) top left no-repeat;
display: block;
float: left;
text-indent: -9999px;
width: 175px;
height: 55px;
}
#navigation {
background: url(../_static/header-line.gif) repeat-x 0 bottom;
display: block;
float: left;
margin: 27px 0 0 25px;
padding: 0;
}
#navigation li{
float: left;
display: block;
margin-right: 25px;
}
#navigation li a {
display: block;
font-weight: normal;
text-decoration: none;
background-position: 50% 0;
padding: 20px 0 5px;
color: #353535;
font-size: 14px;
}
#navigation li a.current, #navigation li a.section {
border-bottom: 3px solid #cf2f19;
color: #cf2f19;
}
div.related {
background-color: #cde2f8;
border: 1px solid #b0d3f8;
}
div.related a {
color: #4078ba;
text-shadow: none;
}
div.sphinxsidebarwrapper {
padding-top: 0;
}
pre {
color: #555;
}
div.documentwrapper h1, div.documentwrapper h2, div.documentwrapper h3, div.documentwrapper h4, div.documentwrapper h5, div.documentwrapper h6 {
font-family: 'PT Sans', sans-serif !important;
color: #264D69;
border-bottom: 1px dotted #C5E2EA;
padding: 0;
background: none;
padding-bottom: 5px;
}
div.documentwrapper h3 {
color: #CF2F19;
}
a.headerlink {
color: #fff !important;
margin-left: 5px;
background: #CF2F19 !important;
}
div.body {
margin-top: -25px;
margin-left: 230px;
}
div.document {
width: 960px;
margin: 0 auto;
}

View File

@ -0,0 +1,117 @@
=================
The Client v2 API
=================
Introduction
============
The main concepts in the Identity v2 API are:
* tenants
* users
* roles
* services
* endpoints
The client v2 API lets you query and make changes through
managers. For example, to manipulate tenants, you interact with a
``keystoneclient.v2_0.tenants.TenantManager`` object.
You obtain access to managers through via attributes of the
``keystoneclient.v2_0.client.Client`` object. For example, the ``tenants``
attribute of the ``Client`` class is a tenant manager::
>>> from keystoneclient.v2_0 import client
>>> keystone = client.Client(...)
>>> keystone.tenants.list() # List tenants
You create a valid ``keystoneclient.v2_0.client.Client`` object by passing
authentication data to the constructor. Authentication and examples of common
tasks are provided below.
You can generally expect that when the client needs to propagate an exception
it will raise an instance of subclass of
``keystoneclient.exceptions.ClientException``
Authenticating
==============
There are two ways to authenticate against Keystone:
* against the admin endpoint with the admin token
* against the public endpoint with a username and password
If you are an administrator, you can authenticate by connecting to the admin
endpoint and using the admin token (sometimes referred to as the service
token). The token is specified as the ``admin_token`` configuration option in
your keystone.conf config file, which is typically in /etc/keystone::
>>> from keystoneclient.v2_0 import client
>>> token = '012345SECRET99TOKEN012345'
>>> endpoint = 'http://192.168.206.130:35357/v2.0'
>>> keystone = client.Client(token=token, endpoint=endpoint)
If you have a username and password, authentication is done against the
public endpoint. You must also specify a tenant that is associated with the
user::
>>> from keystoneclient.v2_0 import client
>>> username='adminUser'
>>> password='secreetword'
>>> tenant_name='openstackDemo'
>>> auth_url='http://192.168.206.130:5000/v2.0'
>>> keystone = client.Client(username=username, password=password,
... tenant_name=tenant_name, auth_url=auth_url)
Creating tenants
================
This example will create a tenant named *openStackDemo*::
>>> from keystoneclient.v2_0 import client
>>> keystone = client.Client(...)
>>> keystone.tenants.create(tenant_name="openstackDemo",
... description="Default Tenant", enabled=True)
<Tenant {u'id': u'9b7962da6eb04745b477ae920ad55939', u'enabled': True, u'description': u'Default Tenant', u'name': u'openstackDemo'}>
Creating users
==============
This example will create a user named *adminUser* with a password *secretword*
in the opoenstackDemo tenant. We first need to retrieve the tenant::
>>> from keystoneclient.v2_0 import client
>>> keystone = client.Client(...)
>>> tenants = keystone.tenants.list()
>>> my_tenant = [x for x in tenants if x.name=='openstackDemo'][0]
>>> my_user = keystone.users.create(name="adminUser",
... password="secretword",
... tenant_id=my_tenant.id)
Creating roles and adding users
===============================
This example will create an admin role and add the *my_user* user to that
role, but only for the *my_tenant* tenant:
>>> from keystoneclient.v2_0 import client
>>> keystone = client.Client(...)
>>> role = keystone.roles.create('admin')
>>> my_tenant = ...
>>> my_user = ...
>>> keystone.roles.add_user_role(my_user, role, my_tenant)
Creating services and endpoints
===============================
This example will create the service and corresponding endpoint for the
Compute service::
>>> from keystoneclient.v2_0 import client
>>> keystone = client.Client(...)
>>> service = keystone.services.create(name="nova", service_type="compute",
... description="Nova Compute Service")
>>> keystone.endpoints.create(
... region="RegionOne", service_id=service.id,
... publicurl="http://192.168.206.130:8774/v2/%(tenant_id)s",
... adminurl="http://192.168.206.130:8774/v2/%(tenant_id)s",
... internalurl="http://192.168.206.130:8774/v2/%(tenant_id)s")

View File

@ -0,0 +1,113 @@
=================
The Client v3 API
=================
Introduction
============
The main concepts in the Identity v3 API are:
* credentials
* domains
* endpoints
* groups
* policies
* projects
* role assignments
* roles
* services
* trusts
* users
The :py:mod:`keystoneclient.v3.client` API lets you query and make changes
through ``managers``. For example, to manipulate a project (formerly
called tenant), you interact with a
:py:class:`keystoneclient.v3.projects.ProjectManager` object.
You obtain access to managers through attributes of a
:py:class:`keystoneclient.v3.client.Client` object. For example, the
``projects`` attribute of a ``Client`` object is a projects manager::
>>> from keystoneclient.v3 import client
>>> keystone = client.Client(...)
>>> keystone.projects.list() # List projects
While it is possible to instantiate a
:py:class:`keystoneclient.v3.client.Client` object (as done above for
clarity), the recommended approach is to use the discovery mechanism
provided by the :py:class:`keystoneclient.client.Client` class. The
appropriate class will be instantiated depending on the API versions
available::
>>> from keystoneclient import client
>>> keystone =
... client.Client(auth_url='http://localhost:5000', ...)
>>> type(keystone)
<class 'keystoneclient.v3.client.Client'>
One can force the use of a specific version of the API, either by
using the ``version`` keyword argument::
>>> from keystoneclient import client
>>> keystone = client.Client(auth_url='http://localhost:5000',
version=(2,), ...)
>>> type(keystone)
<class 'keystoneclient.v2_0.client.Client'>
>>> keystone = client.Client(auth_url='http://localhost:5000',
version=(3,), ...)
>>> type(keystone)
<class 'keystoneclient.v3.client.Client'>
Or by specifying directly the specific API version authentication URL
as the auth_url keyword argument::
>>> from keystoneclient import client
>>> keystone =
... client.Client(auth_url='http://localhost:5000/v2.0', ...)
>>> type(keystone)
<class 'keystoneclient.v2_0.client.Client'>
>>> keystone =
... client.Client(auth_url='http://localhost:5000/v3', ...)
>>> type(keystone)
<class 'keystoneclient.v3.client.Client'>
Upon successful authentication, a :py:class:`keystoneclient.v3.client.Client`
object is returned (when using the Identity v3 API). Authentication and
examples of common tasks are provided below.
You can generally expect that when the client needs to propagate an
exception it will raise an instance of subclass of
``keystoneclient.exceptions.ClientException`` (see
:py:class:`keystoneclient.openstack.common.apiclient.exceptions.ClientException`)
Authenticating
==============
You can authenticate against Keystone using a username, a user domain
name (which will default to 'Default' if it is not specified) and a
password::
>>> from keystoneclient import client
>>> auth_url = 'http://localhost:5000'
>>> username = 'adminUser'
>>> user_domain_name = 'Default'
>>> password = 'secreetword'
>>> keystone = client.Client(auth_url=auth_url, version=(3,),
... username=username, password=password,
... user_domain_name=user_domain_name)
You may optionally specify a domain or project (along with its project
domain name), to obtain a scoped token::
>>> from keystoneclient import client
>>> auth_url = 'http://localhost:5000'
>>> username = 'adminUser'
>>> user_domain_name = 'Default'
>>> project_name = 'demo'
>>> project_domain_name = 'Default'
>>> password = 'secreetword'
>>> keystone = client.Client(auth_url=auth_url, version=(3,),
... username=username, password=password,
... user_domain_name=user_domain_name,
... project_name=project_name,
... project_domain_name=project_domain_name)

View File

@ -0,0 +1,198 @@
==============
Using Sessions
==============
Introduction
============
The :py:class:`keystoneclient.session.Session` class was introduced into
keystoneclient as an attempt to bring a unified interface to the various
OpenStack clients that share common authentication and request parameters
between a variety of services.
The model for using a Session and auth plugin as well as the general terms used
have been heavily inspired by the `requests <http://docs.python-requests.org>`_
library. However neither the Session class nor any of the authentication
plugins rely directly on those concepts from the requests library so you should
not expect a direct translation.
Features
--------
- Common client authentication
Authentication is handled by one of a variety of authentication plugins and
then this authentication information is shared between all the services that
use the same Session object.
- Security maintenance
Security code is maintained in a single place and reused between all
clients such that in the event of problems it can be fixed in a single
location.
- Standard discovery mechanisms
Clients are not expected to have any knowledge of an identity token or any
other form of identification credential. Service and endpoint discovery are
handled by the Session and plugins.
Sessions for Users
==================
The Session object is the contact point to your OpenStack cloud services. It
stores the authentication credentials and connection information required to
communicate with OpenStack such that it can be reused to communicate with many
services. When creating services this Session object is passed to the client
so that it may use this information.
A Session will authenticate on demand. When a request that requires
authentication passes through the Session the authentication plugin will be
asked for a valid token. If a valid token is available it will be used
otherwise the authentication plugin may attempt to contact the authentication
service and fetch a new one.
An example from keystoneclient::
>>> from keystoneclient.auth.identity import v3
>>> from keystoneclient import session
>>> from keystoneclient.v3 import client
>>> auth = v3.Password(auth_url='https://my.keystone.com:5000/v2.0',
... username='myuser',
... password='mypassword',
... project_id='proj')
>>> sess = session.Session(auth=auth,
... verify='/path/to/ca.cert')
>>> ks = client.Client(session=sess)
>>> users = ks.users.list()
As clients adopt this means of operating they will be created in a similar
fashion by passing the Session object to the client's constructor.
Migrating keystoneclient to use a Session
-----------------------------------------
By using a session with a keystonclient Client we define that you have opted in
to new behaviour defined by the session. For example authentication is now
on-demand rather than on creation. To allow this change in behaviour there are
a number of functions that have changed behaviour or are no longer available.
For example the
:py:meth:`keystoneclient.httpclient.HTTPClient.authenticate` command used
to be able to always re-authenticate the current client and fetch a new token.
As this is now controlled by the Session and not the client this has changed,
however the function will still exist to provide compatibility with older
clients.
Likewise certain parameters such as ``user_id`` and ``auth_token`` that used to
be available on the client object post authentication will remain
uninitialized.
When converting an application to use a session object with keystoneclient you
should be aware of the possibility of changes to authentication and
authentication parameters and make sure to test your code thoroughly. It should
have no impact on the typical CRUD interaction with the client.
Sharing Authentication Plugins
------------------------------
A session can only contain one authentication plugin however there is nothing
that specifically binds the authentication plugin to that session, a new
Session can be created that reuses the existing authentication plugin::
>>> new_sess = session.Session(auth=sess.auth,
verify='/path/to/different-cas.cert')
In this case we cannot know which session object will be used when the plugin
performs the authentication call so the command must be able to succeed with
either.
Authentication plugins can also be provided on a per-request basis. This will
be beneficial in a situation where a single session is juggling multiple
authentication credentials::
>>> sess.get('https://my.keystone.com:5000/v3',
auth=my_auth_plugin)
If an auth plugin is provided via parameter then it will override any auth
plugin on the session.
Sessions for Client Developers
==============================
Sessions are intended to take away much of the hassle of dealing with
authentication data and token formats. Clients should be able to specify filter
parameters for selecting the endpoint and have the parsing of the catalog
managed for them.
Authentication
--------------
When making a request with a session object you can simply pass the keyword
parameter ``authenticated`` to indicate whether the argument should contain a
token, by default a token is included if an authentication plugin is available::
>>> # In keystone this route is unprotected by default
>>> resp = sess.get('https://my.keystone.com:5000/v3',
authenticated=False)
Service Discovery
-----------------
In OpenStack the URLs of available services are distributed to the user as a
part of the token they receive called the Service Catalog. Clients are expected
to use the URLs from the Service Catalog rather than have them provided.
In general a client does not need to know the full URL for the server that they
are communicating with, simply that it should send a request to a path
belonging to the correct service.
This is controlled by the ``endpoint_filter`` parameter to a request which
contains all the information an authentication plugin requires to determine the
correct URL to which to send a request. When using this mode only the path for
the request needs to be specified::
>>> resp = session.get('/v3/users',
endpoint_filter={'service_type': 'identity',
'interface': 'public',
'region_name': 'myregion'})
``endpoint_filter`` accepts a number of arguments with which it can determine
an endpoint url:
- ``service_type``: the type of service. For example ``identity``, ``compute``,
``volume`` or many other predefined identifiers.
- ``interface``: the network exposure the interface has. This will be one of:
- ``public``: An endpoint that is available to the wider internet or network.
- ``internal``: An endpoint that is only accessible within the private network.
- ``admin``: An endpoint to be used for administrative tasks.
- ``region_name``: the name of the region where the endpoint resides.
The endpoint filter is a simple key-value filter and can be provided with any
number of arguments. It is then up to the auth plugin to correctly use the
parameters it understands.
The session object determines the URL matching the filter and append to it the
provided path and so create a valid request. If multiple URL matches are found
then any one may be chosen.
While authentication plugins will endeavour to maintain a consistent set of
arguments for an ``endpoint_filter`` the concept of an authentication plugin is
purposefully generic and a specific mechanism may not know how to interpret
certain arguments and ignore them. For example the
:py:class:`keystoneclient.auth.token_endpoint.Token` plugin (which is used when
you want to always use a specific endpoint and token combination) will always
return the same endpoint regardless of the parameters to ``endpoint_filter`` or
a custom OpenStack authentication mechanism may not have the concept of
multiple ``interface`` options and choose to ignore that parameter.
There is some expectation on the user that they understand the limitations of
the authentication system they are using.