shimming in basics from original keystone

This commit is contained in:
Joe Heck 2012-01-19 17:30:27 -08:00
parent ffeb0e558c
commit f40198dece
16 changed files with 1832 additions and 8 deletions

76
docs/generate_autodoc_index.py Executable file
View 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()

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;
}

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,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;
}

View File

View 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 %}

View File

@ -0,0 +1,5 @@
[theme]
inherit = sphinxdoc
stylesheet = sphinxdoc.css
pygments_style = friendly

93
docs/source/community.rst Normal file
View 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.

View File

@ -97,6 +97,18 @@ pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
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 ---------------------------------------------------

135
docs/source/developing.rst Normal file
View 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.

View File

@ -1,17 +1,59 @@
.. keystone documentation master file, created by
sphinx-quickstart on Mon Jan 9 12:02:59 2012.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
..
Copyright 2011 OpenStack, LLC
All Rights Reserved.
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::
:maxdepth: 2
:maxdepth: 1
setup
community
testing
Developers Documentation
========================
.. toctree::
:maxdepth: 1
developing
architecture
sourcecode/autoindex
Indices and tables
==================

View 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>`__

View 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
View 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
View 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 Migrates 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