shimming in basics from original keystone
This commit is contained in:
76
docs/generate_autodoc_index.py
Executable file
76
docs/generate_autodoc_index.py
Executable file
@@ -0,0 +1,76 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""Generates files for sphinx documentation using a simple Autodoc based
|
||||||
|
template.
|
||||||
|
|
||||||
|
To use, just run as a script:
|
||||||
|
$ python doc/generate_autodoc_index.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
base_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
RSTDIR=os.path.join(base_dir, "source", "sourcecode")
|
||||||
|
SOURCEDIR=os.path.join(base_dir, "..")
|
||||||
|
|
||||||
|
# Exclude these modules from the autodoc results
|
||||||
|
EXCLUDE_MODULES = ['keystone.backends.sqlalchemy.migrate_repo']
|
||||||
|
|
||||||
|
def in_exclude_list(module_name):
|
||||||
|
"""Compares a module to the list of excluded modules
|
||||||
|
|
||||||
|
Returns true if the provided module resides in or matches
|
||||||
|
an excluded module, false otherwise.
|
||||||
|
"""
|
||||||
|
for excluded_module in EXCLUDE_MODULES:
|
||||||
|
if module_name.startswith(excluded_module):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def find_autodoc_modules(module_name, sourcedir):
|
||||||
|
"""returns a list of modules in the SOURCE directory"""
|
||||||
|
modlist = []
|
||||||
|
os.chdir(os.path.join(sourcedir, module_name))
|
||||||
|
for root, dirs, files in os.walk("."):
|
||||||
|
for filename in files:
|
||||||
|
if filename.endswith(".py"):
|
||||||
|
# root = ./keystone/test/unit
|
||||||
|
# filename = base.py
|
||||||
|
elements = root.split(os.path.sep)
|
||||||
|
# replace the leading "." with the module name
|
||||||
|
elements[0] = module_name
|
||||||
|
# and get the base module name
|
||||||
|
base, extension = os.path.splitext(filename)
|
||||||
|
if not (base == "__init__"):
|
||||||
|
elements.append(base)
|
||||||
|
result = (".".join(elements))
|
||||||
|
if not in_exclude_list(result):
|
||||||
|
modlist.append(result)
|
||||||
|
return modlist
|
||||||
|
|
||||||
|
if not(os.path.exists(RSTDIR)):
|
||||||
|
os.mkdir(RSTDIR)
|
||||||
|
|
||||||
|
INDEXOUT = open("%s/autoindex.rst" % RSTDIR, "w")
|
||||||
|
INDEXOUT.write("Source Code Index\n")
|
||||||
|
INDEXOUT.write("=================\n")
|
||||||
|
INDEXOUT.write(".. toctree::\n")
|
||||||
|
INDEXOUT.write(" :maxdepth: 1\n")
|
||||||
|
INDEXOUT.write("\n")
|
||||||
|
|
||||||
|
for module in find_autodoc_modules('keystone', SOURCEDIR):
|
||||||
|
generated_file = "%s/%s.rst" % (RSTDIR, module)
|
||||||
|
|
||||||
|
INDEXOUT.write(" %s\n" % module)
|
||||||
|
FILEOUT = open(generated_file, "w")
|
||||||
|
FILEOUT.write("The :mod:`%s` Module\n" % module)
|
||||||
|
FILEOUT.write("=============================="
|
||||||
|
"=============================="
|
||||||
|
"==============================\n")
|
||||||
|
FILEOUT.write(".. automodule:: %s\n" % module)
|
||||||
|
FILEOUT.write(" :members:\n")
|
||||||
|
FILEOUT.write(" :undoc-members:\n")
|
||||||
|
FILEOUT.write(" :show-inheritance:\n")
|
||||||
|
FILEOUT.close()
|
||||||
|
|
||||||
|
INDEXOUT.close()
|
||||||
416
docs/source/_static/basic.css
Normal file
416
docs/source/_static/basic.css
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
230
docs/source/_static/default.css
Normal file
230
docs/source/_static/default.css
Normal 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;
|
||||||
|
}
|
||||||
154
docs/source/_static/jquery.tweet.js
Normal file
154
docs/source/_static/jquery.tweet.js
Normal 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(/(<)+[3]/gi, "<tt class='heart'>♥</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);
|
||||||
65
docs/source/_static/tweaks.css
Normal file
65
docs/source/_static/tweaks.css
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
ul.todo_list {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.todo_list li {
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
padding: 7px 0;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.todo_list li p {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.todo_list li p.link {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.todo_list li p.details {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.todo_list li {
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition {
|
||||||
|
border: 1px solid #8F1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition p.admonition-title {
|
||||||
|
background-color: #8F1000;
|
||||||
|
border-bottom: 1px solid #8E8E8E;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #CF2F19;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related ul li a {
|
||||||
|
color: #CF2F19;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar h4 {
|
||||||
|
background-color:#8E8E8E;
|
||||||
|
border:1px solid #255E6E;
|
||||||
|
color:white;
|
||||||
|
font-size:1em;
|
||||||
|
margin:1em 0 0.5em;
|
||||||
|
padding:0.1em 0 0.1em 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
em {
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.docutils {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a tt {
|
||||||
|
color:#CF2F19;
|
||||||
|
}
|
||||||
0
docs/source/_templates/.placeholder
Normal file
0
docs/source/_templates/.placeholder
Normal file
86
docs/source/_theme/layout.html
Normal file
86
docs/source/_theme/layout.html
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
{% extends "sphinxdoc/layout.html" %}
|
||||||
|
{% set css_files = css_files + ['_static/tweaks.css'] %}
|
||||||
|
{% set script_files = script_files + ['_static/jquery.tweet.js'] %}
|
||||||
|
{% block extrahead %}
|
||||||
|
<script type='text/javascript'>
|
||||||
|
$(document).ready(function(){
|
||||||
|
$("#twitter_feed").tweet({
|
||||||
|
username: "openstack",
|
||||||
|
query: "from:openstack",
|
||||||
|
avatar_size: 32,
|
||||||
|
count: 10,
|
||||||
|
loading_text: "loading tweets..."
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{%- 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 %}
|
||||||
|
|
||||||
|
{%- if pagename == "index" %}
|
||||||
|
<h3>{{ _('Twitter Feed') }}</h3>
|
||||||
|
<div id="twitter_feed" class='twitter_feed'></div>
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
|
||||||
|
{%- endblock %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{%- endif %}{% endif %}
|
||||||
|
{%- endmacro %}
|
||||||
5
docs/source/_theme/theme.conf
Normal file
5
docs/source/_theme/theme.conf
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[theme]
|
||||||
|
inherit = sphinxdoc
|
||||||
|
stylesheet = sphinxdoc.css
|
||||||
|
pygments_style = friendly
|
||||||
|
|
||||||
93
docs/source/community.rst
Normal file
93
docs/source/community.rst
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
..
|
||||||
|
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.
|
||||||
|
|
||||||
|
================
|
||||||
|
Getting Involved
|
||||||
|
================
|
||||||
|
|
||||||
|
The OpenStack community is a very friendly group and there are places online to join in with the
|
||||||
|
community. Feel free to ask questions. This document points you to some of the places where you can
|
||||||
|
communicate with people.
|
||||||
|
|
||||||
|
How to Join the Community
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Our community welcomes all people interested in open source cloud computing, and there are no formal
|
||||||
|
membership requirements. The best way to join the community is to talk with others online or at a meetup
|
||||||
|
and offer contributions through Launchpad_, the wiki_, or blogs. We welcome all types of contributions,
|
||||||
|
from blueprint designs to documentation to testing to deployment scripts.
|
||||||
|
|
||||||
|
.. _Launchpad: https://launchpad.net/keystone
|
||||||
|
.. _wiki: http://wiki.openstack.org/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Contributing Code
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
To contribute code, sign up for a Launchpad account and sign a contributor license agreement,
|
||||||
|
available on the `<http://wiki.openstack.org/CLA>`_. Once the CLA is signed you
|
||||||
|
can contribute code through the Gerrit version control system which is related to your Launchpad account.
|
||||||
|
|
||||||
|
To contribute tests, docs, code, etc, refer to our `Gerrit-Jenkins-Github Workflow`_.
|
||||||
|
|
||||||
|
.. _`Gerrit-Jenkins-Github Workflow`: http://wiki.openstack.org/GerritJenkinsGithub
|
||||||
|
|
||||||
|
|
||||||
|
#openstack on Freenode IRC Network
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
There is a very active chat channel at `<irc://freenode.net/#openstack>`_. This
|
||||||
|
is usually the best place to ask questions and find your way around. IRC stands for Internet Relay
|
||||||
|
Chat and it is a way to chat online in real time. You can also ask a question and come back to the
|
||||||
|
log files to read the answer later. Logs for the #openstack IRC channel are stored at
|
||||||
|
`<http://eavesdrop.openstack.org/irclogs/>`_.
|
||||||
|
|
||||||
|
OpenStack Wiki
|
||||||
|
--------------
|
||||||
|
|
||||||
|
The wiki is a living source of knowledge. It is edited by the community, and
|
||||||
|
has collections of links and other sources of information. Typically the pages are a good place
|
||||||
|
to write drafts for specs or documentation, describe a blueprint, or collaborate with others.
|
||||||
|
|
||||||
|
`OpenStack Wiki <http://wiki.openstack.org/>`_
|
||||||
|
|
||||||
|
Keystone on Launchpad
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Launchpad is a code hosting service that hosts the Keystone source code. From
|
||||||
|
Launchpad you can report bugs, ask questions, and register blueprints (feature requests).
|
||||||
|
|
||||||
|
* `Launchpad Keystone Page <http://launchpad.net/keystone>`_
|
||||||
|
|
||||||
|
OpenStack Blog
|
||||||
|
--------------
|
||||||
|
|
||||||
|
The OpenStack blog includes a weekly newsletter that aggregates OpenStack news
|
||||||
|
from around the internet, as well as providing inside information on upcoming
|
||||||
|
events and posts from OpenStack contributors.
|
||||||
|
|
||||||
|
`OpenStack Blog <http://openstack.org/blog>`_
|
||||||
|
|
||||||
|
See also: `Planet OpenStack <http://planet.openstack.org/>`_, aggregating blogs
|
||||||
|
about OpenStack from around the internet into a single feed. If you'd like to contribute to this blog
|
||||||
|
aggregation with your blog posts, there are instructions for `adding your blog <http://wiki.openstack.org/AddingYourBlog>`_.
|
||||||
|
|
||||||
|
Twitter
|
||||||
|
-------
|
||||||
|
|
||||||
|
Because all the cool kids do it: `@openstack <http://twitter.com/openstack>`_. Also follow the
|
||||||
|
`#openstack <http://search.twitter.com/search?q=%23openstack>`_ tag for relevant tweets.
|
||||||
@@ -97,6 +97,18 @@ pygments_style = 'sphinx'
|
|||||||
# A list of ignored prefixes for module index sorting.
|
# A list of ignored prefixes for module index sorting.
|
||||||
modindex_common_prefix = ['keystone.']
|
modindex_common_prefix = ['keystone.']
|
||||||
|
|
||||||
|
# -- Options for man page output --------------------------------------------
|
||||||
|
|
||||||
|
# Grouping the document tree for man pages.
|
||||||
|
# List of tuples 'sourcefile', 'target', u'title', u'Authors name', 'manual'
|
||||||
|
|
||||||
|
man_pages = [
|
||||||
|
('man/keystone-manage', 'keystone-manage', u'Keystone Management Utility',
|
||||||
|
[u'OpenStack'], 1),
|
||||||
|
('man/keystone', 'keystone', u'Keystone Startup Command',
|
||||||
|
[u'OpenStack'], 1),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTML output ---------------------------------------------------
|
# -- Options for HTML output ---------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
135
docs/source/developing.rst
Normal file
135
docs/source/developing.rst
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
..
|
||||||
|
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.
|
||||||
|
|
||||||
|
========================
|
||||||
|
Developing with Keystone
|
||||||
|
========================
|
||||||
|
|
||||||
|
Get your development environment set up according to :doc:`setup`.
|
||||||
|
|
||||||
|
Running a development instance
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Setting up a virtualenv
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
We recommend establishing a virtualenv to run keystone within. To establish
|
||||||
|
this environment, use the command::
|
||||||
|
|
||||||
|
$ python tools/install_venv.py
|
||||||
|
|
||||||
|
This will create a local virtual environment in the directory ``.venv``.
|
||||||
|
Once created, you can activate this virtualenv for your current shell using::
|
||||||
|
|
||||||
|
$ source .venv/bin/activate
|
||||||
|
|
||||||
|
The virtual environment can be disabled using the command::
|
||||||
|
|
||||||
|
$ deactivate
|
||||||
|
|
||||||
|
You can also use ``tools\with_venv.sh`` to prefix commands so that they run
|
||||||
|
within the virtual environment. For more information on virtual environments,
|
||||||
|
see virtualenv_.
|
||||||
|
|
||||||
|
.. _virtualenv: http://www.virtualenv.org/
|
||||||
|
|
||||||
|
Running Keystone
|
||||||
|
----------------
|
||||||
|
|
||||||
|
To run the keystone Admin and API server instances, use::
|
||||||
|
|
||||||
|
$ tools/with_venv.sh bin/keystone
|
||||||
|
|
||||||
|
Running a demo service that uses Keystone
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
To run client demo (with all auth middleware running locally on sample service)::
|
||||||
|
|
||||||
|
$ tools/with_venv.sh examples/echo/bin/echod
|
||||||
|
|
||||||
|
which spins up a simple "echo" service on port 8090. To use a simple echo client::
|
||||||
|
|
||||||
|
$ python examples/echo/echo_client.py
|
||||||
|
|
||||||
|
Interacting with Keystone
|
||||||
|
=========================
|
||||||
|
|
||||||
|
You can interact with Keystone through the command line using :doc:`man/keystone-manage`
|
||||||
|
which allows you to establish tenants, users, etc.
|
||||||
|
|
||||||
|
You can also interact with Keystone through it's REST API. There is a python
|
||||||
|
keystone client library python-keystoneclient_ which interacts exclusively through
|
||||||
|
the REST API.
|
||||||
|
|
||||||
|
.. _python-keystoneclient: https://github.com/4P/python-keystoneclient
|
||||||
|
|
||||||
|
The easiest way to establish some base information in Keystone to interact with is
|
||||||
|
to invoke::
|
||||||
|
|
||||||
|
$ tools/with_venv.sh bin/sampledata
|
||||||
|
|
||||||
|
You can see the details of what that creates in ``keystone/test/sampledata.py``
|
||||||
|
|
||||||
|
Enabling debugging middleware
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
You can enable a huge amount of additional data (debugging information) about
|
||||||
|
the request and repsonse objects flowing through Keystone using the debugging
|
||||||
|
WSGI middleware.
|
||||||
|
|
||||||
|
To enable this, just modify the pipelines in ``etc/keystone.conf``, from::
|
||||||
|
|
||||||
|
[pipeline:admin]
|
||||||
|
pipeline =
|
||||||
|
urlnormalizer
|
||||||
|
admin_api
|
||||||
|
|
||||||
|
[pipeline:keystone-legacy-auth]
|
||||||
|
pipeline =
|
||||||
|
urlnormalizer
|
||||||
|
legacy_auth
|
||||||
|
d5_compat
|
||||||
|
service_api
|
||||||
|
|
||||||
|
... to::
|
||||||
|
|
||||||
|
[pipeline:admin]
|
||||||
|
pipeline =
|
||||||
|
debug
|
||||||
|
urlnormalizer
|
||||||
|
d5_compat
|
||||||
|
admin_api
|
||||||
|
|
||||||
|
[pipeline:keystone-legacy-auth]
|
||||||
|
pipeline =
|
||||||
|
debug
|
||||||
|
urlnormalizer
|
||||||
|
legacy_auth
|
||||||
|
d5_compat
|
||||||
|
service_api
|
||||||
|
|
||||||
|
Two simple and easy debugging tools are using the ``-d`` when you start keystone::
|
||||||
|
|
||||||
|
$ ./keystone -d
|
||||||
|
|
||||||
|
and the `--trace-calls` flag::
|
||||||
|
|
||||||
|
$ ./keystone -trace-calls
|
||||||
|
|
||||||
|
The ``-d`` flag outputs debug information to the console. The ``--trace-calls`` flag
|
||||||
|
outputs extensive, nested trace calls to the console and highlights any errors
|
||||||
|
in red.
|
||||||
|
|
||||||
@@ -1,17 +1,59 @@
|
|||||||
.. keystone documentation master file, created by
|
..
|
||||||
sphinx-quickstart on Mon Jan 9 12:02:59 2012.
|
Copyright 2011 OpenStack, LLC
|
||||||
You can adapt this file completely to your liking, but it should at least
|
All Rights Reserved.
|
||||||
contain the root `toctree` directive.
|
|
||||||
|
|
||||||
Welcome to keystone's documentation!
|
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
|
||||||
|
|
||||||
Contents:
|
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.
|
||||||
|
|
||||||
|
====================================================
|
||||||
|
Welcome to Keystone, the OpenStack Identity Service!
|
||||||
|
====================================================
|
||||||
|
|
||||||
|
Keystone is a cloud identity service written in Python, which provides
|
||||||
|
authentication, authorization, and an OpenStack service catalog. It
|
||||||
|
implements `OpenStack's Identity API`_.
|
||||||
|
|
||||||
|
This document describes Keystone for contributors of the project, and assumes
|
||||||
|
that you are already familiar with Keystone from an `end-user perspective`_.
|
||||||
|
|
||||||
|
.. _`OpenStack's Identity API`: http://docs.openstack.org/api/openstack-identity-service/2.0/content/
|
||||||
|
.. _`end-user perspective`: http://docs.openstack.org/
|
||||||
|
|
||||||
|
This documentation is generated by the Sphinx toolkit and lives in the source
|
||||||
|
tree. Additional documentation on Keystone and other components of OpenStack can
|
||||||
|
be found on the `OpenStack wiki`_. Also see the :doc:`community` page for
|
||||||
|
other ways to interact with the community.
|
||||||
|
|
||||||
|
.. _`OpenStack wiki`: http://wiki.openstack.org
|
||||||
|
|
||||||
|
Getting Started
|
||||||
|
===============
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 1
|
||||||
|
|
||||||
|
setup
|
||||||
|
community
|
||||||
|
testing
|
||||||
|
|
||||||
|
|
||||||
|
Developers Documentation
|
||||||
|
========================
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
developing
|
||||||
|
architecture
|
||||||
|
sourcecode/autoindex
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
==================
|
==================
|
||||||
|
|||||||
192
docs/source/man/keystone-manage.rst
Normal file
192
docs/source/man/keystone-manage.rst
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
===============
|
||||||
|
keystone-manage
|
||||||
|
===============
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
Keystone Management Utility
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
:Author: keystone@lists.launchpad.net
|
||||||
|
:Date: 2010-11-16
|
||||||
|
:Copyright: OpenStack LLC
|
||||||
|
:Version: 0.1.2
|
||||||
|
:Manual section: 1
|
||||||
|
:Manual group: cloud computing
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
========
|
||||||
|
|
||||||
|
keystone-manage [options]
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
===========
|
||||||
|
|
||||||
|
keystone-manage is the command line tool that interacts with the keystone
|
||||||
|
service to configure Keystone
|
||||||
|
|
||||||
|
USAGE
|
||||||
|
=====
|
||||||
|
|
||||||
|
``keystone-manage [options] type action [additional args]``
|
||||||
|
|
||||||
|
user
|
||||||
|
----
|
||||||
|
|
||||||
|
* **user add** [username] [password]
|
||||||
|
|
||||||
|
adds a user to Keystone's data store
|
||||||
|
|
||||||
|
* **user list**
|
||||||
|
|
||||||
|
lists all users
|
||||||
|
|
||||||
|
* **user disable** [username]
|
||||||
|
|
||||||
|
disables the user *username*
|
||||||
|
|
||||||
|
tenant
|
||||||
|
------
|
||||||
|
|
||||||
|
* **tenant add** [tenant_name]
|
||||||
|
|
||||||
|
adds a tenant to Keystone's data store
|
||||||
|
|
||||||
|
* **tenant list**
|
||||||
|
|
||||||
|
lists all users
|
||||||
|
|
||||||
|
* **tenant disable** [tenant_name]
|
||||||
|
|
||||||
|
role
|
||||||
|
----
|
||||||
|
|
||||||
|
Roles are used to associated users to tenants. Two roles are defined related
|
||||||
|
to the Keystone service in it's configuration file :doc:`../keystone.conf`
|
||||||
|
|
||||||
|
* **role add** [role_name]
|
||||||
|
|
||||||
|
adds a role
|
||||||
|
|
||||||
|
* **role list** ([tenant_name])
|
||||||
|
|
||||||
|
lists all roles, or all roles for tenant, if tenant_name is provided
|
||||||
|
|
||||||
|
* **role grant** [role_name] [username] ([tenant])
|
||||||
|
|
||||||
|
grants a role to a specific user. Granted globally if tenant_name is not
|
||||||
|
provided or granted for a specific tenant if tenant_name is provided.
|
||||||
|
|
||||||
|
service
|
||||||
|
-------
|
||||||
|
|
||||||
|
* **service add** [name] [type] [description] [owner_id]
|
||||||
|
|
||||||
|
adds a service
|
||||||
|
|
||||||
|
* **service list**
|
||||||
|
|
||||||
|
lists all services with id, name, and type
|
||||||
|
|
||||||
|
endpointTemplate
|
||||||
|
----------------
|
||||||
|
|
||||||
|
* **endpointTemplate add** [region] [service_name] [public_url] [admin_url] [internal_url] [enabled] [is_global]
|
||||||
|
|
||||||
|
Add a service endpoint for keystone.
|
||||||
|
|
||||||
|
example::
|
||||||
|
|
||||||
|
keystone-manage endpointTemplates add RegionOne \
|
||||||
|
keystone \
|
||||||
|
http://keystone_host:5000/v2.0 \
|
||||||
|
http://keystone_host:35357/v2.0 \
|
||||||
|
http://keystone_host:5000/v2.0 \
|
||||||
|
1 1
|
||||||
|
|
||||||
|
* **endpointTemplate list** ([tenant_name])
|
||||||
|
|
||||||
|
lists endpoint templates with service, region, and public_url. Restricted to
|
||||||
|
tenant endpoints if tenant_name is provided.
|
||||||
|
|
||||||
|
token
|
||||||
|
-----
|
||||||
|
|
||||||
|
* **token add** [token] [username] [tenant] [expiration]
|
||||||
|
|
||||||
|
adds a token for a given user and tenant with an expiration
|
||||||
|
|
||||||
|
* **token list**
|
||||||
|
|
||||||
|
lists all tokens
|
||||||
|
|
||||||
|
* **token delete** [token]
|
||||||
|
|
||||||
|
deletes the identified token
|
||||||
|
|
||||||
|
endpoint
|
||||||
|
--------
|
||||||
|
|
||||||
|
* **endpoint add** [tenant_name] [endpoint_template]
|
||||||
|
|
||||||
|
adds a tenant-specific endpoint
|
||||||
|
|
||||||
|
credentials
|
||||||
|
-----------
|
||||||
|
|
||||||
|
* **credentials add** [username] [type] [key] [password] ([tenant_name])
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
=======
|
||||||
|
|
||||||
|
--version show program's version number and exit
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
-v, --verbose Print more verbose output
|
||||||
|
-d, --debug Print debugging output to console
|
||||||
|
-c PATH, --config-file=PATH Path to the config file to use. When not
|
||||||
|
specified (the default), we generally look at
|
||||||
|
the first argument specified to be a config
|
||||||
|
file, and if that is also missing, we search
|
||||||
|
standard directories for a config file.
|
||||||
|
-p BIND_PORT, --port=BIND_PORT, --bind-port=BIND_PORT
|
||||||
|
specifies port to listen on (default is 5000)
|
||||||
|
--host=BIND_HOST, --bind-host=BIND_HOST
|
||||||
|
specifies host address to listen on (default
|
||||||
|
is all or 0.0.0.0)
|
||||||
|
-t, --trace-calls Turns on call tracing for troubleshooting
|
||||||
|
-a PORT, --admin-port=PORT Specifies port for Admin API to listen on
|
||||||
|
(default is 35357)
|
||||||
|
|
||||||
|
Logging Options:
|
||||||
|
================
|
||||||
|
|
||||||
|
The following configuration options are specific to logging
|
||||||
|
functionality for this program.
|
||||||
|
|
||||||
|
--log-config=PATH If this option is specified, the logging
|
||||||
|
configuration file specified is used and
|
||||||
|
overrides any other logging options specified.
|
||||||
|
Please see the Python logging module
|
||||||
|
documentation for details on logging
|
||||||
|
configuration files.
|
||||||
|
--log-date-format=FORMAT Format string for %(asctime)s in log records.
|
||||||
|
Default: %Y-%m-%d %H:%M:%S
|
||||||
|
--log-file=PATH (Optional) Name of log file to output to. If
|
||||||
|
not set, logging will go to stdout.
|
||||||
|
--log-dir=LOG_DIR (Optional) The directory to keep log files in
|
||||||
|
(will be prepended to --logfile)
|
||||||
|
|
||||||
|
FILES
|
||||||
|
=====
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
SEE ALSO
|
||||||
|
========
|
||||||
|
|
||||||
|
* `Keystone <http://github.com/openstack/keystone>`__
|
||||||
|
|
||||||
|
SOURCE
|
||||||
|
======
|
||||||
|
|
||||||
|
* Keystone is sourced in GitHub `Keystone <http://github.com/openstack/keystone>`__
|
||||||
|
* Keystone bugs are managed at Launchpad `Launchpad Keystone <https://bugs.launchpad.net/keystone>`__
|
||||||
90
docs/source/man/keystone.rst
Normal file
90
docs/source/man/keystone.rst
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
========
|
||||||
|
keystone
|
||||||
|
========
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
Keystone Management Utility
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
:Author: keystone@lists.launchpad.net
|
||||||
|
:Date: 2010-11-16
|
||||||
|
:Copyright: OpenStack LLC
|
||||||
|
:Version: 0.1.2
|
||||||
|
:Manual section: 1
|
||||||
|
:Manual group: cloud computing
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
========
|
||||||
|
|
||||||
|
keystone [options]
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
===========
|
||||||
|
|
||||||
|
keystone starts both the service and administrative API servers for Keystone.
|
||||||
|
Use :doc:`keystone-control` to stop/start/restart and manage those services
|
||||||
|
once started.
|
||||||
|
|
||||||
|
USAGE
|
||||||
|
=====
|
||||||
|
|
||||||
|
keystone ``keystone [options]``
|
||||||
|
|
||||||
|
Common Options:
|
||||||
|
^^^^^^^^^^^^^^^
|
||||||
|
--version show program's version number and exit
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
|
||||||
|
The following configuration options are common to all keystone
|
||||||
|
programs.::
|
||||||
|
|
||||||
|
-v, --verbose Print more verbose output
|
||||||
|
-d, --debug Print debugging output to console
|
||||||
|
-c PATH, --config-file=PATH Path to the config file to use. When not
|
||||||
|
specified (the default), we generally look at
|
||||||
|
the first argument specified to be a config
|
||||||
|
file, and if that is also missing, we search
|
||||||
|
standard directories for a config file.
|
||||||
|
-p BIND_PORT, --port=BIND_PORT, --bind-port=BIND_PORT
|
||||||
|
specifies port to listen on (default is 5000)
|
||||||
|
--host=BIND_HOST, --bind-host=BIND_HOST
|
||||||
|
specifies host address to listen on (default
|
||||||
|
is all or 0.0.0.0)
|
||||||
|
-t, --trace-calls Turns on call tracing for troubleshooting
|
||||||
|
-a PORT, --admin-port=PORT Specifies port for Admin API to listen on
|
||||||
|
(default is 35357)
|
||||||
|
|
||||||
|
Logging Options:
|
||||||
|
^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The following configuration options are specific to logging
|
||||||
|
functionality for this program.::
|
||||||
|
|
||||||
|
--log-config=PATH If this option is specified, the logging
|
||||||
|
configuration file specified is used and
|
||||||
|
overrides any other logging options specified.
|
||||||
|
Please see the Python logging module
|
||||||
|
documentation for details on logging
|
||||||
|
configuration files.
|
||||||
|
--log-date-format=FORMAT Format string for %(asctime)s in log records.
|
||||||
|
Default: %Y-%m-%d %H:%M:%S
|
||||||
|
--log-file=PATH (Optional) Name of log file to output to. If
|
||||||
|
not set, logging will go to stdout.
|
||||||
|
--log-dir=LOG_DIR (Optional) The directory to keep log files in
|
||||||
|
(will be prepended to --logfile)
|
||||||
|
|
||||||
|
FILES
|
||||||
|
=====
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
SEE ALSO
|
||||||
|
========
|
||||||
|
|
||||||
|
* `Keystone <http://github.com/openstack/keystone>`__
|
||||||
|
|
||||||
|
SOURCE
|
||||||
|
======
|
||||||
|
|
||||||
|
* Keystone is sourced in GitHub `Keystone <http://github.com/openstack/keystone>`__
|
||||||
|
* Keystone bugs are managed at Launchpad `Launchpad Keystone <https://bugs.launchpad.net/keystone>`__
|
||||||
151
docs/source/setup.rst
Normal file
151
docs/source/setup.rst
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
..
|
||||||
|
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.
|
||||||
|
|
||||||
|
=============================================
|
||||||
|
Setting up a Keystone development environment
|
||||||
|
=============================================
|
||||||
|
|
||||||
|
This document describes setting up keystone directly from GitHub_
|
||||||
|
for development purposes.
|
||||||
|
|
||||||
|
To install keystone from packaging, refer instead to Keystone's `User Documentation`_.
|
||||||
|
|
||||||
|
.. _GitHub: http://github.com/openstack/keystone
|
||||||
|
.. _`User Documentation`: http://docs.openstack.org/
|
||||||
|
|
||||||
|
Prerequisites
|
||||||
|
=============
|
||||||
|
|
||||||
|
This document assumes you are using:
|
||||||
|
|
||||||
|
- Ubuntu 11.10, Fedora 15, or Mac OS X Lion
|
||||||
|
- `Python 2.7`_
|
||||||
|
|
||||||
|
.. _`Python 2.7`: http://www.python.org/
|
||||||
|
|
||||||
|
And that you have the following tools available on your system:
|
||||||
|
|
||||||
|
- git_
|
||||||
|
- setuptools_
|
||||||
|
- pip_
|
||||||
|
|
||||||
|
**Reminder**: If you're successfully using a different platform, or a
|
||||||
|
different version of the above, please document your configuration here!
|
||||||
|
|
||||||
|
.. _git: http://git-scm.com/
|
||||||
|
.. _setuptools: http://pypi.python.org/pypi/setuptools
|
||||||
|
|
||||||
|
Getting the latest code
|
||||||
|
=======================
|
||||||
|
|
||||||
|
You can clone our latest code from our `Github repository`::
|
||||||
|
|
||||||
|
$ git clone https://github.com/openstack/keystone.git
|
||||||
|
|
||||||
|
When that is complete, you can::
|
||||||
|
|
||||||
|
$ cd keystone
|
||||||
|
|
||||||
|
.. _`Github repository`: https://github.com/openstack/keystone
|
||||||
|
|
||||||
|
Installing dependencies
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Keystone maintains a list of PyPi_ dependencies, designed for use by
|
||||||
|
pip_.
|
||||||
|
|
||||||
|
.. _PyPi: http://pypi.python.org/
|
||||||
|
.. _pip: http://pypi.python.org/pypi/pip
|
||||||
|
|
||||||
|
However, your system *may* need additional dependencies that `pip` (and by
|
||||||
|
extension, PyPi) cannot satisfy. These dependencies should be installed
|
||||||
|
prior to using `pip`, and the installation method may vary depending on
|
||||||
|
your platform.
|
||||||
|
|
||||||
|
Ubuntu 11.10::
|
||||||
|
|
||||||
|
$ sudo apt-get install python-dev libxml2-dev libxslt1-dev libsasl2-dev libsqlite3-dev libssl-dev libldap2-dev
|
||||||
|
|
||||||
|
Fedora 15::
|
||||||
|
|
||||||
|
$ sudo yum install python-sqlite2 python-lxml python-greenlet-devel python-ldap
|
||||||
|
|
||||||
|
Mac OS X Lion (requires MacPorts_)::
|
||||||
|
|
||||||
|
$ sudo port install py-ldap
|
||||||
|
|
||||||
|
.. _MacPorts: http://www.macports.org/
|
||||||
|
|
||||||
|
PyPi Packages
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Assuming you have any necessary binary packages & header files available
|
||||||
|
on your system, you can then install PyPi dependencies.
|
||||||
|
|
||||||
|
You may also need to prefix `pip install` with `sudo`, depending on your
|
||||||
|
environment::
|
||||||
|
|
||||||
|
# Describe dependencies (including non-PyPi dependencies)
|
||||||
|
$ cat tools/pip-requires
|
||||||
|
|
||||||
|
# Install all PyPi dependencies (for production, testing, and development)
|
||||||
|
$ pip install -r tools/pip-requires
|
||||||
|
|
||||||
|
Updating your PYTHONPATH
|
||||||
|
========================
|
||||||
|
|
||||||
|
There are a number of methods for getting Keystone into your PYTHON PATH,
|
||||||
|
the easiest of which is::
|
||||||
|
|
||||||
|
# Fake-install the project by symlinking Keystone into your Python site-packages
|
||||||
|
$ python setup.py develop
|
||||||
|
|
||||||
|
You should then be able to `import keystone` from your Python shell
|
||||||
|
without issue::
|
||||||
|
|
||||||
|
>>> import keystone.version
|
||||||
|
>>>
|
||||||
|
|
||||||
|
If you want to check the version of Keystone you are running:
|
||||||
|
|
||||||
|
>>> print keystone.version.version()
|
||||||
|
2012.1-dev
|
||||||
|
|
||||||
|
|
||||||
|
If you can import keystone successfully, you should be ready to move on to :doc:`testing`.
|
||||||
|
|
||||||
|
Troubleshooting
|
||||||
|
===============
|
||||||
|
|
||||||
|
Eventlet segfaults on RedHat / Fedora
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
[*If this is no longer an issue, please remove this section, thanks!*]
|
||||||
|
|
||||||
|
On some OSes, specifically Fedora 15, the current versions of
|
||||||
|
greenlet/eventlet segfault when running keystone. To fix this, install
|
||||||
|
the development versions of greenlet and eventlet::
|
||||||
|
|
||||||
|
$ pip uninstall greenlet eventlet
|
||||||
|
$ cd <appropriate working directory>
|
||||||
|
$ hg clone https://bitbucket.org/ambroff/greenlet
|
||||||
|
$ cd greenlet
|
||||||
|
$ sudo python setup.py install
|
||||||
|
|
||||||
|
$ cd <appropriate working directory>
|
||||||
|
$ hg clone https://bitbucket.org/which_linden/eventlet
|
||||||
|
$ cd greenlet
|
||||||
|
$ sudo python setup.py install
|
||||||
77
docs/source/testing.rst
Normal file
77
docs/source/testing.rst
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
================
|
||||||
|
Testing Keystone
|
||||||
|
================
|
||||||
|
|
||||||
|
Keystone uses a number of testing methodologies to ensure correctness.
|
||||||
|
|
||||||
|
Running Built-In Tests
|
||||||
|
======================
|
||||||
|
|
||||||
|
To run the full suites of tests maintained within Keystone, run::
|
||||||
|
|
||||||
|
$ ./run_tests.sh --with-progress
|
||||||
|
|
||||||
|
This shows realtime feedback during test execution, and iterates over
|
||||||
|
multiple configuration variations.
|
||||||
|
|
||||||
|
This differs from how tests are executed from the continuous integration
|
||||||
|
environment. Specifically, Jenkins doesn't care about realtime progress,
|
||||||
|
and aborts after the first test failure (a fail-fast behavior)::
|
||||||
|
|
||||||
|
$ ./run_tests.sh
|
||||||
|
|
||||||
|
Testing Schema Migrations
|
||||||
|
=========================
|
||||||
|
|
||||||
|
The application of schema migrations can be tested using SQLAlchemy Migrate’s built-in test runner, one migration at a time.
|
||||||
|
|
||||||
|
.. WARNING::
|
||||||
|
|
||||||
|
This may leave your database in an inconsistent state; attempt this in non-production environments only!
|
||||||
|
|
||||||
|
This is useful for testing the *next* migration in sequence (both forward & backward) in a database under version control::
|
||||||
|
|
||||||
|
$ python keystone/backends/sqlalchemy/migrate_repo/manage.py test --url=sqlite:///test.db --repository=keystone/backends/sqlalchemy/migrate_repo/
|
||||||
|
|
||||||
|
This command refers to a SQLite database used for testing purposes. Depending on the migration, this command alone does not make assertions as to the integrity of your data during migration.
|
||||||
|
|
||||||
|
Writing Tests
|
||||||
|
=============
|
||||||
|
|
||||||
|
Tests are maintained in the ``keystone.test`` module. Unit tests are
|
||||||
|
isolated from functional tests.
|
||||||
|
|
||||||
|
Functional Tests
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The ``keystone.test.functional.common`` module provides a ``unittest``-based
|
||||||
|
``httplib`` client which you can extend and use for your own tests.
|
||||||
|
Generally, functional tests should serve to illustrate intended use cases
|
||||||
|
and API behaviors. To help make your tests easier to read, the test client:
|
||||||
|
|
||||||
|
- Authenticates with a known user name and password combination
|
||||||
|
- Asserts 2xx HTTP status codes (unless told otherwise)
|
||||||
|
- Abstracts keystone REST verbs & resources into single function calls
|
||||||
|
|
||||||
|
Testing Multiple Configurations
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
Several variations of the default configuration are iterated over to
|
||||||
|
ensure test coverage of mutually exclusive featuresets, such as the
|
||||||
|
various backend options.
|
||||||
|
|
||||||
|
These configuration templates are maintained in ``keystone/test/etc`` and
|
||||||
|
are iterated over by ``run_tests.py``.
|
||||||
|
|
||||||
|
Further Testing
|
||||||
|
===============
|
||||||
|
|
||||||
|
devstack_ is the *best* way to quickly deploy keystone with the rest of the
|
||||||
|
OpenStack universe and should be critical step in your development workflow!
|
||||||
|
|
||||||
|
You may also be interested in either the `OpenStack Continuous Integration Project`_
|
||||||
|
or the `OpenStack Integration Testing Project`_.
|
||||||
|
|
||||||
|
.. _devstack: http://devstack.org/
|
||||||
|
.. _OpenStack Continuous Integration Project: https://github.com/openstack/openstack-ci
|
||||||
|
.. _OpenStack Integration Testing Project: https://github.com/openstack/openstack-integration-tests
|
||||||
Reference in New Issue
Block a user