Migrate api-ref into our tree

Per this email[0], it's time to migrate our API docs into our tree.

This copies the sphinx extension from nova into our tree as well, which
will be later split into its own python module. At that time we can cut
over to the module and drop it from our tree.

The conf.py and the tox environment are also cribbed from nova.

[0] http://lists.openstack.org/pipermail/openstack-dev/2016-May/093765.html

Change-Id: I683cc4d6459d77c42951a06247b6f9ff8f8456bd
This commit is contained in:
Jim Rollenhagen 2016-05-03 13:24:10 -04:00
parent 97b7ba98fc
commit fa098f69e4
27 changed files with 2260 additions and 0 deletions

0
api-ref/ext/__init__.py Normal file
View File

View File

@ -0,0 +1,377 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""This provides a sphinx extension able to create the HTML needed
for the api-ref website.
It contains 2 new stanzas.
.. rest_method:: GET /foo/bar
Which is designed to be used as the first stanza in a new section to
state that section is about that REST method. During processing the
rest stanza will be reparented to be before the section in question,
and used as a show/hide selector for it's details.
.. rest_parameters:: file.yaml
- name1: name_in_file1
- name2: name_in_file2
- name3: name_in_file3
Which is designed to build structured tables for either response or
request parameters. The stanza takes a value which is a file to lookup
details about the parameters in question.
The contents of the stanza are a yaml list of key / value pairs. The
key is the name of the parameter to be shown in the table. The value
is the key in the file.yaml where all other metadata about the
parameter will be extracted. This allows for reusing parameter
definitions widely in API definitions, but still providing for control
in both naming and ordering of parameters at every declaration.
"""
from docutils import nodes
from docutils.parsers.rst.directives.tables import Table
from docutils.statemachine import ViewList
from sphinx.util.compat import Directive
import yaml
def full_name(cls):
return cls.__module__ + '.' + cls.__name__
class rest_method(nodes.Part, nodes.Element):
"""rest_method custom node type
We specify a custom node type for rest_method so that we can
accumulate all the data about the rest method, but not render as
part of the normal rendering process. This means that we need a
renderer for every format we wish to support with this.
"""
pass
class rest_expand_all(nodes.Part, nodes.Element):
pass
class RestExpandAllDirective(Directive):
has_content = True
def run(self):
return [rest_expand_all()]
class RestMethodDirective(Directive):
# this enables content in the directive
has_content = True
def run(self):
lineno = self.state_machine.abs_line_number()
target = nodes.target()
section = nodes.section(classes=["detail-control"])
# env = self.state.document.settings.env
# env.app.info("Parent %s" % self.state.parent.attributes)
node = rest_method()
# TODO(sdague): this is a super simplistic parser, should be
# more robust.
method, sep, url = self.content[0].partition(' ')
node['method'] = method
node['url'] = url
node['target'] = self.state.parent.attributes['ids'][0]
# We need to build a temporary target that we can replace
# later in the processing to get the TOC to resolve correctly.
temp_target = "%s-selector" % node['target']
target = nodes.target(ids=[temp_target])
self.state.add_target(temp_target, '', target, lineno)
section += node
return [target, section]
class RestParametersDirective(Table):
headers = ["Name", "In", "Type", "Description"]
def yaml_from_file(self, fpath):
"""Collect Parameter stanzas from inline + file.
This allows use to reference an external file for the actual
parameter definitions.
"""
# self.app.info("Fpath: %s" % fpath)
try:
with open(fpath, 'r') as stream:
lookup = yaml.load(stream)
except IOError:
self.env.warn(
self.env.docname,
"Parameters file %s not found" % fpath)
return
except yaml.YAMLError as exc:
self.app.warn(exc)
raise
content = "\n".join(self.content)
parsed = yaml.load(content)
# self.app.info("Params loaded is %s" % parsed)
# self.app.info("Lookup table looks like %s" % lookup)
new_content = list()
for paramlist in parsed:
for name, ref in paramlist.items():
if ref in lookup:
new_content.append((name, lookup[ref]))
else:
# TODO(sdague): this provides a kind of confusing
# error message because env.warn isn't meant to be
# used this way, however it does provide a way to
# track down where the parameters list is that is
# wrong. So it's good enough for now.
self.env.warn(
"%s:%s " % (
self.state_machine.node.source,
self.state_machine.node.line),
("No field definition for ``%s`` found in ``%s``. "
" Skipping." % (ref, fpath)))
# self.app.info("New content %s" % new_content)
self.yaml = new_content
def run(self):
self.env = self.state.document.settings.env
self.app = self.env.app
# Make sure we have some content, which should be yaml that
# defines some parameters.
if not self.content:
error = self.state_machine.reporter.error(
'No parameters defined',
nodes.literal_block(self.block_text, self.block_text),
line=self.lineno)
return [error]
if not len(self.arguments) >= 1:
self.state_machine.reporter.error(
'No reference file defined',
nodes.literal_block(self.block_text, self.block_text),
line=self.lineno)
return [error]
# NOTE(sdague): it's important that we pop the arg otherwise
# we end up putting the filename as the table caption.
rel_fpath, fpath = self.env.relfn2path(self.arguments.pop())
self.yaml_file = fpath
self.yaml_from_file(self.yaml_file)
self.max_cols = len(self.headers)
# TODO(sdague): it would be good to dynamically set column
# widths (or basically make the colwidth thing go away
# entirely)
self.options['widths'] = (20, 10, 10, 60)
self.col_widths = self.get_column_widths(self.max_cols)
# Actually convert the yaml
title, messages = self.make_title()
# self.app.info("Title %s, messages %s" % (title, messages))
table_node = self.build_table()
self.add_name(table_node)
if title:
table_node.insert(0, title)
return [table_node] + messages
def get_rows(self, table_data):
rows = []
groups = []
trow = nodes.row()
entry = nodes.entry()
para = nodes.paragraph(text=unicode(table_data))
entry += para
trow += entry
rows.append(trow)
return rows, groups
# Add a column for a field. In order to have the RST inside
# these fields get rendered, we need to use the
# ViewList. Note, ViewList expects a list of lines, so chunk
# up our content as a list to make it happy.
def add_col(self, value):
entry = nodes.entry()
result = ViewList(value.split('\n'))
self.state.nested_parse(result, 0, entry)
return entry
def show_no_yaml_error(self):
trow = nodes.row(classes=["no_yaml"])
trow += self.add_col("No yaml found %s" % self.yaml_file)
trow += self.add_col("")
trow += self.add_col("")
trow += self.add_col("")
return trow
def collect_rows(self):
rows = []
groups = []
try:
# self.app.info("Parsed content is: %s" % self.yaml)
for key, values in self.yaml:
min_version = values.get('min_version', '')
desc = values.get('description', '')
classes = []
if min_version:
desc += ("\n\n**New in version %s**\n" % min_version)
min_ver_css_name = ("rp_min_ver_" +
str(min_version).replace('.', '_'))
classes.append(min_ver_css_name)
trow = nodes.row(classes=classes)
name = key
if values.get('required', False) is False:
name += " (Optional)"
trow += self.add_col(name)
trow += self.add_col(values.get('in'))
trow += self.add_col(values.get('type'))
trow += self.add_col(desc)
rows.append(trow)
except AttributeError as exc:
if 'key' in locals():
self.app.warn("Failure on key: %s, values: %s. %s" %
(key, values, exc))
else:
rows.append(self.show_no_yaml_error())
return rows, groups
def build_table(self):
table = nodes.table()
tgroup = nodes.tgroup(cols=len(self.headers))
table += tgroup
# TODO(sdague): it would be really nice to figure out how not
# to have this stanza, it kind of messes up all of the table
# formatting because it doesn't let tables just be the right
# size.
tgroup.extend(
nodes.colspec(colwidth=col_width, colname='c' + str(idx))
for idx, col_width in enumerate(self.col_widths)
)
thead = nodes.thead()
tgroup += thead
row_node = nodes.row()
thead += row_node
row_node.extend(nodes.entry(h, nodes.paragraph(text=h))
for h in self.headers)
tbody = nodes.tbody()
tgroup += tbody
rows, groups = self.collect_rows()
tbody.extend(rows)
table.extend(groups)
return table
def rest_method_html(self, node):
tmpl = """
<div class="row operation-grp">
<div class="col-md-1 operation">
<a name="%(target)s" class="operation-anchor" href="#%(target)s">
<span class="glyphicon glyphicon-link"></span></a>
<span class="label label-success">%(method)s</span>
</div>
<div class="col-md-5">%(url)s</div>
<div class="col-md-5">%(desc)s</div>
<div class="col-md-1">
<button
class="btn btn-info btn-sm btn-detail"
data-target="#%(target)s-detail"
data-toggle="collapse"
id="%(target)s-detail-btn"
>detail</button>
</div>
</div>"""
self.body.append(tmpl % node)
raise nodes.SkipNode
def rest_expand_all_html(self, node):
tmpl = """
<div>
<div class=col-md-11></div>
<div class=col-md-1>
<button id="expand-all"
data-toggle="collapse"
class="btn btn-info btn-sm btn-expand-all"
>Show All</button>
</div>
</div>"""
self.body.append(tmpl % node)
raise nodes.SkipNode
def resolve_rest_references(app, doctree):
for node in doctree.traverse():
if isinstance(node, rest_method):
rest_node = node
rest_method_section = node.parent
rest_section = rest_method_section.parent
gp = rest_section.parent
# Added required classes to the top section
rest_section.attributes['classes'].append('api-detail')
rest_section.attributes['classes'].append('collapse')
# Pop the title off the collapsed section
title = rest_section.children.pop(0)
rest_node['desc'] = title.children[0]
# In order to get the links in the sidebar to be right, we
# have to do some id flipping here late in the game. The
# rest_method_section has basically had a dummy id up
# until this point just to keep it from colliding with
# it's parent.
rest_section.attributes['ids'][0] = (
"%s-detail" % rest_section.attributes['ids'][0])
rest_method_section.attributes['ids'][0] = rest_node['target']
# Pop the overall section into it's grand parent,
# right before where the current parent lives
idx = gp.children.index(rest_section)
rest_section.remove(rest_method_section)
gp.insert(idx, rest_method_section)
def setup(app):
app.add_node(rest_method,
html=(rest_method_html, None))
app.add_node(rest_expand_all,
html=(rest_expand_all_html, None))
app.add_directive('rest_parameters', RestParametersDirective)
app.add_directive('rest_method', RestMethodDirective)
app.add_directive('rest_expand_all', RestExpandAllDirective)
app.add_stylesheet('bootstrap.min.css')
app.add_stylesheet('api-site.css')
app.add_javascript('bootstrap.min.js')
app.add_javascript('api-site.js')
app.connect('doctree-read', resolve_rest_references)
return {'version': '0.1'}

View File

@ -0,0 +1,81 @@
tt.literal {
padding: 2px 4px;
font-size: 90%;
color: #c7254e;
white-space: nowrap;
background-color: #f9f2f4;
border-radius: 4px;
}
/* bootstrap users blockquote for pull quotes, so they are much
larger, we need them smaller */
blockquote { font-size: 1em; }
pre {
display: block;
padding: 9.5px;
margin: 0 0 10px;
font-size: 13px;
line-height: 1.428571429;
color: #333;
word-break: break-all;
word-wrap: break-word;
background-color: #f5f5f5;
border: 1px solid #ccc;
border-radius: 4px;
}
tbody>tr:nth-child(odd)>td,
tbody>tr:nth-child(odd)>th {
background-color: #f9f9f9;
}
table>thead>tr>th, table>tbody>tr>th, table>tfoot>tr>th, table>thead>tr>td, table>tbody>tr>td, table>tfoot>tr>td {
padding: 8px;
line-height: 1.428571429;
vertical-align: top;
border-top: 1px solid #ddd;
}
td>p {
margin: 0 0 0.5em;
}
div.document {
width: 80% !important;
}
@media (max-width: 1200px) {
div.document {
width: 960px !important;
}
}
.operation-grp {
padding-top: 0.5em;
padding-bottom: 1em;
}
/* Ensure the method buttons and their links don't split lines when
the page is narrower */
.operation {
/* this moves the link icon into the gutter */
margin-left: -1.25em;
margin-right: 1.25em;
white-space: nowrap;
}
/* These make the links only show up on hover */
a.operation-anchor {
visibility: hidden;
}
.operation-grp:hover a.operation-anchor {
visibility: visible;
}
/* All tables for requests should be full width */
.api-detail table.docutils {
width: 100%;
}

View File

@ -0,0 +1,110 @@
(function() {
var pageCache;
$(document).ready(function() {
pageCache = $('.api-documentation').html();
// Show the proper JSON/XML example when toggled
$('.example-select').on('change', function(e) {
$(e.currentTarget).find(':selected').tab('show')
});
// Change the text on the expando buttons when appropriate
$('.api-detail')
.on('hide.bs.collapse', function(e) {
processButton(this, 'detail');
})
.on('show.bs.collapse', function(e) {
processButton(this, 'close');
});
var expandAllActive = true;
// Expand the world
$('#expand-all').click(function () {
if (expandAllActive) {
expandAllActive = false;
$('.api-detail').collapse('show');
$('#expand-all').attr('data-toggle', '');
$(this).text('Hide All');
} else {
expandAllActive = true;
$('.api-detail').collapse('hide');
$('#expand-all').attr('data-toggle', 'collapse');
$(this).text('Show All');
}});
// Wire up the search button
$('#search-btn').on('click', function(e) {
searchPage();
});
// Wire up the search box enter
$('#search-box').on('keydown', function(e) {
if (e.keyCode === 13) {
searchPage();
return false;
}
});
});
/**
* highlight terms based on the regex in the provided $element
*/
function highlightTextNodes($element, regex) {
var markup = $element.html();
// Do regex replace
// Inject span with class of 'highlighted termX' for google style highlighting
$element.html(markup.replace(regex, '>$1<span class="highlight">$2</span>$3<'));
}
function searchPage() {
$(".api-documentation").html(pageCache);
//make sure that all div's are expanded/hidden accordingly
$('.api-detail.in').each(function (e) {
$(this).collapse('hide');
});
var startTime = new Date().getTime(),
searchTerm = $('#search-box').val();
// The regex is the secret, it prevents text within tag declarations to be affected
var regex = new RegExp(">([^<]*)?(" + searchTerm + ")([^>]*)?<", "ig");
highlightTextNodes($('.api-documentation'), regex);
// Once we've highlighted the node, lets expand any with a search match in them
$('.api-detail').each(function () {
var $elem = $(this);
if ($elem.html().indexOf('<span class="highlight">') !== -1) {
$elem.collapse('show');
processButton($elem, 'close');
}
});
// log the results
if (console.log) {
console.log("search completed in: " + ((new Date().getTime()) - startTime) + "ms");
}
$('.api-detail')
.on('hide.bs.collapse', function (e) {
processButton(this, 'detail');
})
.on('show.bs.collapse', function (e) {
processButton(this, 'close');
});
}
/**
* Helper function for setting the text, styles for expandos
*/
function processButton(button, text) {
$('#' + $(button).attr('id') + '-btn').text(text)
.toggleClass('btn-info')
.toggleClass('btn-default');
}
})();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,303 @@
.. -*- rst -*-
=================
Chassis (chassis)
=================
Chassis operations.
List chassis with details
=========================
.. rest_method:: GET /v1/chassis/detail
Lists all chassis with details.
Normal response codes: 200
Error response codes:413,405,404,403,401,400,503,
Request
-------
.. rest_parameters:: parameters.yaml
- limit: limit
- marker: marker
- sort_dir: sort_dir
- sort_key: sort_key
Response Parameters
-------------------
.. rest_parameters:: parameters.yaml
- uuid: uuid
- chassis: chassis
- description: description
- extra: extra
Response Example
----------------
.. literalinclude:: samples/chassis-list-details-response.json
:language: javascript
Show chassis details
====================
.. rest_method:: GET /v1/chassis/{chassis_id}
Shows details for a chassis.
Normal response codes: 200
Error response codes:413,405,404,403,401,400,503,
Request
-------
.. rest_parameters:: parameters.yaml
- fields: fields
Response Parameters
-------------------
.. rest_parameters:: parameters.yaml
- uuid: uuid
- chassis: chassis
- description: description
- extra: extra
Response Example
----------------
.. literalinclude:: samples/chassis-show-response.json
:language: javascript
Update chassis
==============
.. rest_method:: PATCH /v1/chassis/{chassis_id}
Updates a chassis.
Normal response codes: 200
Error response codes:413,415,405,404,403,401,400,503,409,
Request
-------
.. rest_parameters:: parameters.yaml
- chassis: chassis
- description: description
- extra: extra
Request Example
---------------
.. literalinclude:: samples/chassis-update-request.json
:language: javascript
Response Parameters
-------------------
.. rest_parameters:: parameters.yaml
- description: description
- links: links
- extra: extra
- created_at: created_at
- updated_at: updated_at
- chassis: chassis
- nodes: nodes
- uuid: uuid
Response Example
----------------
.. literalinclude:: samples/chassis-show-response.json
:language: javascript
Delete chassis
==============
.. rest_method:: DELETE /v1/chassis/{chassis_id}
Deletes a chassis.
Error response codes:204,413,415,405,404,403,401,400,503,409,
Request
-------
Create chassis
==============
.. rest_method:: POST /v1/chassis
Creates a chassis.
Error response codes:201,413,415,405,404,403,401,400,503,409,
Request
-------
.. rest_parameters:: parameters.yaml
- chassis: chassis
- description: description
- extra: extra
Request Example
---------------
.. literalinclude:: samples/chassis-create-request.json
:language: javascript
Response Parameters
-------------------
.. rest_parameters:: parameters.yaml
- description: description
- links: links
- extra: extra
- created_at: created_at
- updated_at: updated_at
- nodes: nodes
- uuid: uuid
List chassis
============
.. rest_method:: GET /v1/chassis
Lists all chassis.
Normal response codes: 200
Error response codes:413,405,404,403,401,400,503,
Request
-------
.. rest_parameters:: parameters.yaml
- limit: limit
- marker: marker
- sort_dir: sort_dir
- sort_key: sort_key
- fields: fields
Response Parameters
-------------------
.. rest_parameters:: parameters.yaml
- uuid: uuid
- chassis: chassis
- description: description
- extra: extra
Response Example
----------------
.. literalinclude:: samples/chassis-list-response.json
:language: javascript

View File

@ -0,0 +1,242 @@
.. -*- rst -*-
=================
Drivers (drivers)
=================
Show driver details
===================
.. rest_method:: GET /v1/drivers/{driver_name}
Shows details for a driver.
Normal response codes: 200
Error response codes:413,405,404,403,401,400,503,
Request
-------
.. rest_parameters:: parameters.yaml
- driver_name: driver_name
Response Parameters
-------------------
.. rest_parameters:: parameters.yaml
- hosts: hosts
- name: name
Response Example
----------------
.. literalinclude:: samples/driver-get-response.json
:language: javascript
Show driver properties
======================
.. rest_method:: GET /v1/drivers/{driver_name}/properties
Shows properties for a driver.
Normal response codes: 200
Error response codes:413,405,404,403,401,400,503,
Request
-------
.. rest_parameters:: parameters.yaml
- driver_name: driver_name
Response Parameters
-------------------
.. rest_parameters:: parameters.yaml
- hosts: hosts
- name: name
- links: links
- properties: properties
Response Example
----------------
.. literalinclude:: samples/driver-get-response.json
:language: javascript
List drivers
============
.. rest_method:: GET /v1/drivers
Lists all drivers.
Normal response codes: 200
Error response codes:413,405,404,403,401,400,503,
Request
-------
Response Parameters
-------------------
.. rest_parameters:: parameters.yaml
- drivers: drivers
- hosts: hosts
- name: name
Response Example
----------------
.. literalinclude:: samples/drivers-list-response.json
:language: javascript
Show driver logical disk properties
===================================
.. rest_method:: GET /v1/drivers/{driver_name}/raid/logical_disk_properties
Shows logical disk properties for a driver.
Normal response codes: 200
Error response codes:413,405,404,403,401,400,503,
Request
-------
.. rest_parameters:: parameters.yaml
- driver_name: driver_name
Response Parameters
-------------------
.. rest_parameters:: parameters.yaml
- hosts: hosts
- name: name
- links: links
- properties: properties
Response Example
----------------
.. literalinclude:: samples/driver-get-response.json
:language: javascript
Show driver vendor methods
==========================
.. rest_method:: GET /v1/drivers/{driver_name}/vendor_passthru/methods
Shows vendor methods for a driver.
Normal response codes: 200
Error response codes:413,405,404,403,401,400,503,
Request
-------
.. rest_parameters:: parameters.yaml
- driver_name: driver_name
Response Parameters
-------------------
.. rest_parameters:: parameters.yaml
- hosts: hosts
- name: name
- links: links
- properties: properties
Response Example
----------------
.. literalinclude:: samples/driver-get-response.json
:language: javascript

View File

@ -0,0 +1,216 @@
.. -*- rst -*-
=============
Nodes (nodes)
=============
Show node details
=================
.. rest_method:: GET /v1/nodes/{node_id}
Shows details for a node.
Normal response codes: 200
Error response codes:413,405,404,403,401,400,503,
Request
-------
.. rest_parameters:: parameters.yaml
- node_id: node_id
- fields: fields
Response Example
----------------
.. literalinclude:: samples/node-show-response.json
:language: javascript
Update node
===========
.. rest_method:: PATCH /v1/nodes/{node_id}
Updates a node.
Normal response codes: 200
Error response codes:413,415,405,404,403,401,400,503,409,
Request
-------
.. rest_parameters:: parameters.yaml
- node_id: node_id
Response Example
----------------
.. literalinclude:: samples/node-show-response.json
:language: javascript
Delete node
===========
.. rest_method:: DELETE /v1/nodes/{node_id}
Deletes a node.
Error response codes:204,413,415,405,404,403,401,400,503,409,
Request
-------
.. rest_parameters:: parameters.yaml
- node_id: node_id
List nodes with details
=======================
.. rest_method:: GET /v1/nodes/detail
Lists all nodes with details.
Normal response codes: 200
Error response codes:413,405,404,403,401,400,503,
Request
-------
Response Example
----------------
.. literalinclude:: samples/nodes-list-details-response.json
:language: javascript
Create node
===========
.. rest_method:: POST /v1/nodes
Creates a node.
Error response codes:201,413,415,405,404,403,401,400,503,409,
Request
-------
List nodes
==========
.. rest_method:: GET /v1/nodes
Lists all nodes.
Normal response codes: 200
Error response codes:413,405,404,403,401,400,503,
Request
-------
Response Example
----------------
.. literalinclude:: samples/nodes-list-response.json
:language: javascript

View File

@ -0,0 +1,208 @@
.. -*- rst -*-
=============
Ports (ports)
=============
Show port details
=================
.. rest_method:: GET /v1/ports/{port_id}
Shows details for a port.
Normal response codes: 200
Error response codes:413,405,404,403,401,400,503,
Request
-------
.. rest_parameters:: parameters.yaml
- port_id: port_id
- fields: fields
Response Example
----------------
TODO
Update port
===========
.. rest_method:: PATCH /v1/ports/{port_id}
Updates a port.
Normal response codes: 200
Error response codes:413,415,405,404,403,401,400,503,409,
Request
-------
.. rest_parameters:: parameters.yaml
- port_id: port_id
Response Example
----------------
TODO
Delete port
===========
.. rest_method:: DELETE /v1/ports/{port_id}
Deletes a port.
Error response codes:204,413,415,405,404,403,401,400,503,409,
Request
-------
.. rest_parameters:: parameters.yaml
- port_id: port_id
List ports with details
=======================
.. rest_method:: GET /v1/ports/detail
Lists all ports with details.
Normal response codes: 200
Error response codes:413,405,404,403,401,400,503,
Request
-------
Response Example
----------------
TODO
Create port
===========
.. rest_method:: POST /v1/ports
Creates a port.
Error response codes:201,413,415,405,404,403,401,400,503,409,
Request
-------
List ports
==========
.. rest_method:: GET /v1/ports
Lists all ports.
Normal response codes: 200
Error response codes:413,405,404,403,401,400,503,
Request
-------
Response Example
----------------
TODO

217
api-ref/source/conf.py Normal file
View File

@ -0,0 +1,217 @@
# -*- coding: utf-8 -*-
#
# 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.
#
# ironic documentation build configuration file, created by
# sphinx-quickstart on Sat May 1 15:17:47 2010.
#
# This file is execfile()d with the current directory set to
# its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import os
import subprocess
import sys
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath('../../'))
sys.path.insert(0, os.path.abspath('../'))
sys.path.insert(0, os.path.abspath('./'))
# -- General configuration ----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
'ext.rest_parameters',
'oslosphinx',
]
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#
# source_encoding = 'utf-8'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Ironic API Reference'
copyright = u'OpenStack Foundation'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
from ironic.version import version_info
# The full version, including alpha/beta/rc tags.
release = version_info.release_string()
# The short X.Y version.
version = version_info.version_string()
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
# today = ''
# Else, today_fmt is used as the format for a strftime call.
# today_fmt = '%B %d, %Y'
# The reST default role (used for this markup: `text`) to use
# for all documents.
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
add_module_names = False
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# -- Options for man page output ----------------------------------------------
# Grouping the document tree for man pages.
# List of tuples 'sourcefile', 'target', u'title', u'Authors name', 'manual'
# -- Options for HTML output --------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
# html_theme_path = ["."]
# html_theme = '_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
# html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
# html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
# html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
# html_last_updated_fmt = '%b %d, %Y'
git_cmd = ["git", "log", "--pretty=format:'%ad, commit %h'", "--date=local",
"-n1"]
html_last_updated_fmt = subprocess.Popen(
git_cmd, stdout=subprocess.PIPE).communicate()[0]
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
# html_additional_pages = {}
# If false, no module index is generated.
# html_use_modindex = True
# If false, no index is generated.
# html_use_index = True
# If true, the index is split into individual pages for each letter.
# html_split_index = False
# If true, links to the reST sources are added to the pages.
# html_show_sourcelink = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
# html_use_opensearch = ''
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
# html_file_suffix = ''
# Output file base name for HTML help builder.
htmlhelp_basename = 'ironicdoc'
# -- Options for LaTeX output -------------------------------------------------
# The paper size ('letter' or 'a4').
# latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
# latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass
# [howto/manual]).
latex_documents = [
('index', 'Ironic.tex', u'OpenStack Bare Metal API Documentation',
u'OpenStack Foundation', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
# latex_use_parts = False
# Additional stuff for the LaTeX preamble.
# latex_preamble = ''
# Documents to append as an appendix to all manuals.
# latex_appendices = []
# If false, no module index is generated.
# latex_use_modindex = True

13
api-ref/source/index.rst Normal file
View File

@ -0,0 +1,13 @@
:tocdepth: 2
================
Bare Metal API
================
.. rest_expand_all::
.. include:: baremetal-api-v1-chassis.inc
.. include:: baremetal-api-v1-drivers.inc
.. include:: baremetal-api-v1-nodes.inc
.. include:: baremetal-api-v1-ports.inc

View File

@ -0,0 +1,214 @@
# variables in header
x-openstack-request-id:
description: >
foo
in: header
required: false
type: string
# variables in path
driver_name:
description: |
The name of the driver.
in: path
required: false
type: string
node_id:
description: |
The UUID of the node.
in: path
required: false
type: string
port_id:
description: |
The UUID of the port.
in: path
required: false
type: string
# variables in query
fields:
description: |
One or more chassis fields to be returned in the response.
For example, the following request returns only the ``description``
field for each chassis:
::
GET /v1/chassis?fields=description
in: query
required: false
type: array
limit:
description: |
Requests a page size of items. Returns a number
of items up to a limit value. Use the ``limit`` parameter to make
an initial limited request and use the ID of the last-seen item
from the response as the ``marker`` parameter value in a
subsequent limited request.
in: query
required: false
type: integer
marker:
description: |
The ID of the last-seen item. Use the ``limit``
parameter to make an initial limited request and use the ID of the
last-seen item from the response as the ``marker`` parameter value
in a subsequent limited request.
in: query
required: false
type: string
sort_dir:
description: |
Sorts the response by the requested sort
direction. A valid value is ``asc`` (ascending) or ``desc``
(descending). Default is ``asc``. You can specify multiple pairs
of sort key and sort direction query parameters. If you omit the
sort direction in a pair, the API uses the natural sorting
direction of the server attribute that is provided as the
``sort_key``.
in: query
required: false
type: string
sort_key:
description: |
Sorts the response by the this attribute value.
Default is ``id``. You can specify multiple pairs of sort key and
sort direction query parameters. If you omit the sort direction in
a pair, the API uses the natural sorting direction of the server
attribute that is provided as the ``sort_key``.
in: query
required: false
type: string
# variables in body
chassis:
description: |
A ``chassis`` object.
in: body
required: true
type: array
chassis_1:
description: |
A list of chassis objects.
in: body
required: true
type: array
created_at:
description: |
The date and time when the resource was created.
The date and time stamp format is `ISO 8601
<https://en.wikipedia.org/wiki/ISO_8601>`_:
::
CCYY-MM-DDThh:mm:ss±hh:mm
For example, ``2015-08-27T09:49:58-05:00``.
The ``±hh:mm`` value, if included, is the time zone as an offset
from UTC.
in: body
required: true
type: string
description:
description: |
A description for the chassis.
in: body
required: false
type: string
description_1:
description: |
A description for the chassis.
in: body
required: true
type: string
drivers:
description: |
A list of ``drivers`` objects.
in: body
required: true
type: array
extra:
description: |
A set of one or more arbitrary metadata key and
value pairs for the chassis.
in: body
required: false
type: object
extra_1:
description: |
A set of zero or more arbitrary metadata key and
value pairs for the chassis.
in: body
required: true
type: object
hosts:
description: |
A list of active hosts that support this driver.
in: body
required: true
type: array
links:
description: |
A list that contains a self link and associated
chassis links.
in: body
required: true
type: array
links_1:
description: |
A list of relative links. Includes the self and
bookmark links.
in: body
required: true
type: array
name:
description: |
The name of the driver.
in: body
required: true
type: string
nodes:
description: |
Links to the collection of nodes contained in
this chassis.
in: body
required: true
type: array
properties:
description: |
A list of links to driver properties.
in: body
required: true
type: array
updated_at:
description: |
The date and time when the resource was updated.
The date and time stamp format is `ISO 8601
<https://en.wikipedia.org/wiki/ISO_8601>`_:
::
CCYY-MM-DDThh:mm:ss±hh:mm
For example, ``2015-08-27T09:49:58-05:00``.
The ``±hh:mm`` value, if included, is the time zone as an offset
from UTC. In the previous example, the offset value is ``-05:00``.
If the ``updated_at`` date and time stamp is not set, its value is
``null``.
in: body
required: true
type: string
uuid:
description: |
The UUID for the chassis.
in: body
required: true
type: string

View File

@ -0,0 +1,7 @@
{
"chassis": [
{
"description": "Sample chassis"
}
]
}

View File

@ -0,0 +1,18 @@
{
"chassis": [
{
"description": "Sample chassis",
"links": [
{
"href": "http://localhost:6385/v1/chassis/eaaca217-e7d8-47b4-bb41-3f99f20eed89",
"rel": "self"
},
{
"href": "http://localhost:6385/chassis/eaaca217-e7d8-47b4-bb41-3f99f20eed89",
"rel": "bookmark"
}
],
"uuid": "eaaca217-e7d8-47b4-bb41-3f99f20eed89"
}
]
}

View File

@ -0,0 +1,18 @@
{
"chassis": [
{
"description": "Sample chassis",
"links": [
{
"href": "http://localhost:6385/v1/chassis/eaaca217-e7d8-47b4-bb41-3f99f20eed89",
"rel": "self"
},
{
"href": "http://localhost:6385/chassis/eaaca217-e7d8-47b4-bb41-3f99f20eed89",
"rel": "bookmark"
}
],
"uuid": "eaaca217-e7d8-47b4-bb41-3f99f20eed89"
}
]
}

View File

@ -0,0 +1,27 @@
{
"created_at": "2000-01-01T12:00:00",
"description": "Sample chassis",
"extra": {},
"links": [
{
"href": "http://localhost:6385/v1/chassis/eaaca217-e7d8-47b4-bb41-3f99f20eed89",
"rel": "self"
},
{
"href": "http://localhost:6385/chassis/eaaca217-e7d8-47b4-bb41-3f99f20eed89",
"rel": "bookmark"
}
],
"nodes": [
{
"href": "http://localhost:6385/v1/chassis/eaaca217-e7d8-47b4-bb41-3f99f20eed89/nodes",
"rel": "self"
},
{
"href": "http://localhost:6385/chassis/eaaca217-e7d8-47b4-bb41-3f99f20eed89/nodes",
"rel": "bookmark"
}
],
"updated_at": "2000-01-01T12:00:00",
"uuid": "eaaca217-e7d8-47b4-bb41-3f99f20eed89"
}

View File

@ -0,0 +1,7 @@
{
"chassis": [
{
"description": "Sample chassis"
}
]
}

View File

@ -0,0 +1,6 @@
{
"hosts": [
"fake-host"
],
"name": "sample-driver"
}

View File

@ -0,0 +1,10 @@
{
"drivers": [
{
"hosts": [
"fake-host"
],
"name": "sample-driver"
}
]
}

View File

@ -0,0 +1,63 @@
{
"chassis_uuid": "edcad704-b2da-41d5-96d9-afd580ecfa12",
"clean_step": {},
"console_enabled": false,
"created_at": "2000-01-01T12:00:00",
"driver": "fake",
"driver_info": {},
"driver_internal_info": {},
"extra": {},
"inspection_finished_at": null,
"inspection_started_at": "2000-01-01T12:00:00",
"instance_info": {},
"instance_uuid": "dcf1fbc5-93fc-4596-9395-b80572f6267b",
"last_error": null,
"links": [
{
"href": "http://localhost:6385/v1/nodes/1be26c0b-03f2-4d2e-ae87-c02d7f33c123",
"rel": "self"
},
{
"href": "http://localhost:6385/nodes/1be26c0b-03f2-4d2e-ae87-c02d7f33c123",
"rel": "bookmark"
}
],
"maintenance": false,
"maintenance_reason": null,
"name": "database16-dc02",
"ports": [
{
"href": "http://localhost:6385/v1/nodes/1be26c0b-03f2-4d2e-ae87-c02d7f33c123/ports",
"rel": "self"
},
{
"href": "http://localhost:6385/nodes/1be26c0b-03f2-4d2e-ae87-c02d7f33c123/ports",
"rel": "bookmark"
}
],
"power_state": "power on",
"properties": {
"cpus": "1",
"local_gb": "10",
"memory_mb": "1024"
},
"provision_state": "active",
"provision_updated_at": "2000-01-01T12:00:00",
"raid_config": null,
"reservation": null,
"states": [
{
"href": "http://localhost:6385/v1/nodes/1be26c0b-03f2-4d2e-ae87-c02d7f33c123/states",
"rel": "self"
},
{
"href": "http://localhost:6385/nodes/1be26c0b-03f2-4d2e-ae87-c02d7f33c123/states",
"rel": "bookmark"
}
],
"target_power_state": null,
"target_provision_state": null,
"target_raid_config": null,
"updated_at": "2000-01-01T12:00:00",
"uuid": "1be26c0b-03f2-4d2e-ae87-c02d7f33c123"
}

View File

@ -0,0 +1,11 @@
{
"console_enabled": false,
"last_error": null,
"power_state": "power on",
"provision_state": null,
"provision_updated_at": null,
"raid_config": null,
"target_power_state": "power on",
"target_provision_state": "active",
"target_raid_config": null
}

View File

@ -0,0 +1,64 @@
{
"nodes": [
{
"chassis_uuid": "633f9f21-5bd5-4166-b811-1eb01490c4ab",
"clean_step": {},
"console_enabled": false,
"created_at": "2016-04-23T10:52:43+00:00",
"driver": "pxe_ssh",
"driver_info": {
"deploy_kernel": "aadebece-ce44-4cf6-a9e8-545f0e8ac9f3",
"deploy_ramdisk": "cfe6f9ce-b2e6-4a7a-9246-0cc7eeb89a71",
"ssh_address": "localhost",
"ssh_key_filename": "/opt/stack/data/ironic/ssh_keys/ironic_key",
"ssh_port": 22,
"ssh_username": "ubuntu",
"ssh_virt_type": "virsh"
},
"driver_internal_info": {},
"extra": {},
"inspection_finished_at": null,
"inspection_started_at": null,
"instance_info": {},
"instance_uuid": null,
"last_error": null,
"links": [
{
"href": "http://localhost:6385/v1/nodes/277c9fe9-a385-4e45-9399-660f3287e48c",
"rel": "self"
},
{
"href": "http://localhost:6385/nodes/277c9fe9-a385-4e45-9399-660f3287e48c",
"rel": "bookmark"
}
],
"maintenance": false,
"maintenance_reason": null,
"name": "node-0",
"ports": [
{
"href": "http://localhost:6385/v1/nodes/277c9fe9-a385-4e45-9399-660f3287e48c/ports",
"rel": "self"
},
{
"href": "http://localhost:6385/nodes/277c9fe9-a385-4e45-9399-660f3287e48c/ports",
"rel": "bookmark"
}
],
"power_state": "power off",
"properties": {
"cpu_arch": "x86_64",
"cpus": 1,
"local_gb": 10,
"memory_mb": 1024
},
"provision_state": "available",
"provision_updated_at": null,
"reservation": null,
"target_power_state": null,
"target_provision_state": null,
"updated_at": "2016-04-23T10:53:37+00:00",
"uuid": "277c9fe9-a385-4e45-9399-660f3287e48c"
}
]
}

View File

@ -0,0 +1,22 @@
{
"nodes": [
{
"instance_uuid": "dcf1fbc5-93fc-4596-9395-b80572f6267b",
"links": [
{
"href": "http://localhost:6385/v1/nodes/1be26c0b-03f2-4d2e-ae87-c02d7f33c123",
"rel": "self"
},
{
"href": "http://localhost:6385/nodes/1be26c0b-03f2-4d2e-ae87-c02d7f33c123",
"rel": "bookmark"
}
],
"maintenance": false,
"name": "database16-dc02",
"power_state": "power on",
"provision_state": "active",
"uuid": "1be26c0b-03f2-4d2e-ae87-c02d7f33c123"
}
]
}

15
tox.ini
View File

@ -66,6 +66,21 @@ envdir = {toxworkdir}/venv
commands =
python setup.py build_sphinx
[testenv:api-ref]
# This environment is called from CI scripts to test and publish
# the API Ref to developer.openstack.org.
# NOTE(sdague): this target does not use constraints because
# upstream infra does not yet support it. Once that's fixed, we can
# drop the install_command.
#
# we do not used -W here because we are doing some slightly tricky
# things to build a single page document, and as such, we are ok
# ignoring the duplicate stanzas warning.
install_command = pip install -U --force-reinstall {opts} {packages}
commands =
rm -rf api-ref/build
sphinx-build -W -b html -d api-ref/build/doctrees api-ref/source api-ref/build/html
[testenv:releasenotes]
# NOTE(amrith) The setting of the install_command in this location
# is only required because currently infra does not actually