[docs] Remove outdated docs
the whole doc dir was copy-pasted from github.com/openstack/rally project while splitting plugins for OpenStack from framework part. Most of these documents are quite general and out-dated. Let's remove them and start writting from scratch. Anyway, if needed we can copy something useful from git history or from framework repo. Change-Id: Icf9c522a9e554d6ac735e573fe2ddf06862cd46f
@ -1,47 +0,0 @@
|
||||
========================
|
||||
Content of doc directory
|
||||
========================
|
||||
|
||||
This directory contains everything that is related to documentation and
|
||||
bureaucracy. You can find here 4 subdirectories:
|
||||
|
||||
|
||||
feature_request
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
If some use case is not covered by Rally, it is the right place to request it.
|
||||
To request new feature you should just explain use case on high level.
|
||||
Technical details and writing code are not required at all.
|
||||
|
||||
|
||||
source
|
||||
~~~~~~
|
||||
|
||||
Source of documentation. Latest version of documentation_.
|
||||
|
||||
.. _documentation: https://rally.readthedocs.io/en/latest/
|
||||
|
||||
|
||||
specs
|
||||
~~~~~
|
||||
|
||||
Specs are detailed description of proposed changes in project.
|
||||
Usually they answer on what, why, how to change in project and who is going to work on change.
|
||||
|
||||
|
||||
user_stories
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Place where you can share any of Rally user experience. E.g. fixing some bugs,
|
||||
measuring performance of different architectures or comparing different
|
||||
hardware and so on..
|
||||
|
||||
|
||||
release_notes
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
The latest.rst_ contains new features and API changes of Rally's latest release.
|
||||
And you could find all old releases in archive_.
|
||||
|
||||
.. _latest.rst: https://github.com/openstack/rally/blob/master/doc/release_notes/latest.rst
|
||||
.. _archive: https://github.com/openstack/rally/tree/master/doc/release_notes/archive
|
@ -1,208 +0,0 @@
|
||||
# Copyright 2016: Mirantis Inc.
|
||||
# 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.
|
||||
|
||||
import copy
|
||||
import inspect
|
||||
|
||||
from docutils.parsers import rst
|
||||
|
||||
from rally.cli import cliutils
|
||||
from rally.cli import main
|
||||
import utils
|
||||
|
||||
|
||||
class Parser(object):
|
||||
"""A simplified interface of argparse.ArgumentParser"""
|
||||
def __init__(self):
|
||||
self.parsers = {}
|
||||
self.subparser = None
|
||||
self.defaults = {}
|
||||
self.arguments = []
|
||||
|
||||
def add_parser(self, name, help=None, description=None,
|
||||
formatter_class=None):
|
||||
parser = Parser()
|
||||
self.parsers[name] = {"description": description,
|
||||
"help": help,
|
||||
"fclass": formatter_class,
|
||||
"parser": parser}
|
||||
return parser
|
||||
|
||||
def set_defaults(self, command_object=None, action_fn=None,
|
||||
action_kwargs=None):
|
||||
if command_object:
|
||||
self.defaults["command_object"] = command_object
|
||||
if action_fn:
|
||||
self.defaults["action_fn"] = action_fn
|
||||
if action_kwargs:
|
||||
self.defaults["action_kwargs"] = action_kwargs
|
||||
|
||||
def add_subparsers(self, dest):
|
||||
# NOTE(andreykurilin): there is only one expected call
|
||||
if self.subparser:
|
||||
raise ValueError("Can't add one more subparser.")
|
||||
self.subparser = Parser()
|
||||
return self.subparser
|
||||
|
||||
def add_argument(self, *args, **kwargs):
|
||||
if "action_args" in args:
|
||||
return
|
||||
self.arguments.append((args, kwargs))
|
||||
|
||||
|
||||
DEFAULT_UUIDS_CMD = {
|
||||
"deployment": ["rally deployment create"],
|
||||
"task": ["rally task start"],
|
||||
"verification": ["rally verify start", "rally verify import_results"]
|
||||
}
|
||||
|
||||
|
||||
def compose_note_about_default_uuids(argument, dest):
|
||||
# TODO(andreykurilin): add references to commands
|
||||
return utils.note(
|
||||
"The default value for the ``%(arg)s`` argument is taken from "
|
||||
"the Rally environment. Usually, the default value is equal to"
|
||||
" the UUID of the last successful run of ``%(cmd)s``, if the "
|
||||
"``--no-use`` argument was not used." % {
|
||||
"arg": argument,
|
||||
"cmd": "``, ``".join(DEFAULT_UUIDS_CMD[dest])})
|
||||
|
||||
|
||||
def compose_use_cmd_hint_msg(cmd):
|
||||
return utils.hint(
|
||||
"You can set the default value by executing ``%(cmd)s <uuid>``"
|
||||
" (ref__).\n\n __ #%(ref)s" % {"cmd": cmd,
|
||||
"ref": cmd.replace(" ", "-")})
|
||||
|
||||
|
||||
def make_arguments_section(category_name, cmd_name, arguments, defaults):
|
||||
elements = [utils.paragraph("**Command arguments**:")]
|
||||
for args, kwargs in arguments:
|
||||
# for future changes...
|
||||
# :param args: a single command argument which can represented by
|
||||
# several names(for example, --uuid and --task-id) in cli.
|
||||
# :type args: tuple
|
||||
# :param kwargs: description of argument. Have next format:
|
||||
# {"dest": "action_kwarg_<name of keyword argument in code>",
|
||||
# "help": "just a description of argument"
|
||||
# "metavar": "[optional] metavar of argument. Example:"
|
||||
# "Example: argument '--file'; metavar 'path' ",
|
||||
# "type": "[optional] class object of argument's type",
|
||||
# "required": "[optional] boolean value"}
|
||||
# :type kwargs: dict
|
||||
dest = kwargs.get("dest").replace("action_kwarg_", "")
|
||||
description = []
|
||||
if cmd_name != "use":
|
||||
# lets add notes about specific default values and hint about
|
||||
# "use" command with reference
|
||||
if dest in ("deployment", "task"):
|
||||
description.append(compose_note_about_default_uuids(
|
||||
args[0], dest))
|
||||
description.append(
|
||||
compose_use_cmd_hint_msg("rally %s use" % dest))
|
||||
elif dest == "verification":
|
||||
description.append(compose_note_about_default_uuids(
|
||||
args[0], dest))
|
||||
description.append(
|
||||
compose_use_cmd_hint_msg("rally verify use"))
|
||||
|
||||
description.append(kwargs.get("help"))
|
||||
|
||||
action = kwargs.get("action")
|
||||
if not action:
|
||||
arg_type = kwargs.get("type")
|
||||
if arg_type:
|
||||
description.append("**Type**: %s" % arg_type.__name__)
|
||||
|
||||
skip_default = dest in ("deployment",
|
||||
"task_id",
|
||||
"verification")
|
||||
if not skip_default and dest in defaults:
|
||||
description.append("**Default**: %s" % defaults[dest])
|
||||
metavar = kwargs.get("metavar")
|
||||
|
||||
ref = "%s_%s_%s" % (category_name, cmd_name, args[0].replace("-", ""))
|
||||
|
||||
if metavar:
|
||||
args = ["%s %s" % (arg, metavar) for arg in args]
|
||||
|
||||
elements.extend(utils.make_definition(", ".join(args),
|
||||
ref, description))
|
||||
return elements
|
||||
|
||||
|
||||
def get_defaults(func):
|
||||
"""Return a map of argument:default_value for specified function."""
|
||||
spec = inspect.getargspec(func)
|
||||
if spec.defaults:
|
||||
return dict(zip(spec.args[-len(spec.defaults):], spec.defaults))
|
||||
return {}
|
||||
|
||||
|
||||
def make_command_section(category_name, name, parser):
|
||||
section = utils.subcategory("rally %s %s" % (category_name, name))
|
||||
section.extend(utils.parse_text(parser["description"]))
|
||||
if parser["parser"].arguments:
|
||||
defaults = get_defaults(parser["parser"].defaults["action_fn"])
|
||||
section.extend(make_arguments_section(
|
||||
category_name, name, parser["parser"].arguments, defaults))
|
||||
return section
|
||||
|
||||
|
||||
def make_category_section(name, parser):
|
||||
category_obj = utils.category("Category: %s" % name)
|
||||
# NOTE(andreykurilin): we are re-using `_add_command_parsers` method from
|
||||
# `rally.cli.cliutils`, but, since it was designed to print help message,
|
||||
# generated description for categories contains specification for all
|
||||
# sub-commands. We don't need information about sub-commands at this point,
|
||||
# so let's skip "generated description" and take it directly from category
|
||||
# class.
|
||||
description = parser.defaults["command_object"].__doc__
|
||||
# TODO(andreykurilin): write a decorator which will mark cli-class as
|
||||
# deprecated without changing its docstring.
|
||||
if description.startswith("[Deprecated"):
|
||||
i = description.find("]")
|
||||
msg = description[1:i]
|
||||
description = description[i + 1:].strip()
|
||||
category_obj.append(utils.warning(msg))
|
||||
category_obj.extend(utils.parse_text(description))
|
||||
|
||||
for command in sorted(parser.subparser.parsers.keys()):
|
||||
subparser = parser.subparser.parsers[command]
|
||||
category_obj.append(make_command_section(name, command, subparser))
|
||||
return category_obj
|
||||
|
||||
|
||||
class CLIReferenceDirective(rst.Directive):
|
||||
optional_arguments = 1
|
||||
option_spec = {"group": str}
|
||||
|
||||
def run(self):
|
||||
parser = Parser()
|
||||
categories = copy.copy(main.categories)
|
||||
if "group" in self.options:
|
||||
categories = {k: v for k, v in categories.items()
|
||||
if k == self.options["group"]}
|
||||
cliutils._add_command_parsers(categories, parser)
|
||||
|
||||
content = []
|
||||
for cg in sorted(categories.keys()):
|
||||
content.append(make_category_section(
|
||||
cg, parser.parsers[cg]["parser"]))
|
||||
return content
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.add_directive("make_cli_reference", CLIReferenceDirective)
|
@ -1,57 +0,0 @@
|
||||
# Copyright 2017: Mirantis Inc.
|
||||
# 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.
|
||||
|
||||
from docutils import nodes
|
||||
import json
|
||||
|
||||
from oslo_utils import importutils
|
||||
|
||||
|
||||
def include_var(name, rawtext, text, lineno, inliner, options=None,
|
||||
content=None):
|
||||
"""include variable
|
||||
|
||||
:param name: The local name of the interpreted role, the role name
|
||||
actually used in the document.
|
||||
:param rawtext: A string containing the enitre interpreted text input,
|
||||
including the role and markup. Return it as a problematic
|
||||
node linked to a system message if a problem is
|
||||
encountered.
|
||||
:param text: The interpreted text content.
|
||||
:param lineno: The line number where the interpreted text begins.
|
||||
:param inliner: The docutils.parsers.rst.states.Inliner object that
|
||||
called include_var. It contains the several attributes
|
||||
useful for error reporting and document tree access.
|
||||
:param options: A dictionary of directive options for customization
|
||||
(from the 'role' directive), to be interpreted by the
|
||||
role function. Used for additional attributes for the
|
||||
generated elements and other functionality.
|
||||
:param content: A list of strings, the directive content for
|
||||
customization (from the 'role' directive). To be
|
||||
interpreted by the role function.
|
||||
:return:
|
||||
"""
|
||||
obj = importutils.import_class(text)
|
||||
if isinstance(obj, (tuple, list)):
|
||||
obj = ", ".join(obj)
|
||||
elif isinstance(obj, dict):
|
||||
obj = json.dumps(dict, indent=4)
|
||||
else:
|
||||
obj = str(obj)
|
||||
return [nodes.Text(obj)], []
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.add_role("include-var", include_var)
|
@ -1,385 +0,0 @@
|
||||
# Copyright 2015: Mirantis Inc.
|
||||
# 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.
|
||||
|
||||
import copy
|
||||
from docutils.parsers import rst
|
||||
import json
|
||||
import re
|
||||
|
||||
from rally.common.plugin import discover
|
||||
from rally.common.plugin import plugin
|
||||
from rally.common import validation
|
||||
from rally import plugins
|
||||
import utils
|
||||
|
||||
|
||||
JSON_SCHEMA_TYPES_MAP = {"boolean": "bool",
|
||||
"string": "str",
|
||||
"number": "float",
|
||||
"integer": "int",
|
||||
"array": "list",
|
||||
"object": "dict"}
|
||||
|
||||
|
||||
def process_jsonschema(schema):
|
||||
"""Process jsonschema and make it looks like regular docstring."""
|
||||
|
||||
if not schema:
|
||||
# nothing to parse
|
||||
return
|
||||
|
||||
if "type" in schema:
|
||||
|
||||
# str
|
||||
if schema["type"] == "string":
|
||||
doc = schema.get("description", "")
|
||||
if "pattern" in schema:
|
||||
doc += ("\n\nShould follow next pattern: %s." %
|
||||
schema["pattern"])
|
||||
return {"doc": doc, "type": "str"}
|
||||
|
||||
# int or float
|
||||
elif schema["type"] in ("integer", "number"):
|
||||
doc = schema.get("description", "")
|
||||
if "minimum" in schema:
|
||||
doc += "\n\nMin value: %s." % schema["minimum"]
|
||||
if "maximum" in schema:
|
||||
doc += "\n\nMax value: %s." % schema["maximum"]
|
||||
return {"doc": doc, "type": JSON_SCHEMA_TYPES_MAP[schema["type"]]}
|
||||
|
||||
# bool or null
|
||||
elif schema["type"] in ("boolean", "null"):
|
||||
return {"doc": schema.get("description", ""),
|
||||
"type": "bool" if schema["type"] == "boolean" else "null"}
|
||||
|
||||
# list
|
||||
elif schema["type"] == "array":
|
||||
info = {"doc": schema.get("description", ""),
|
||||
"type": "list"}
|
||||
|
||||
if "items" in schema:
|
||||
if info["doc"]:
|
||||
info["doc"] += "\n\n"
|
||||
info["doc"] += ("Elements of the list should follow format(s) "
|
||||
"described below:\n\n")
|
||||
|
||||
items = schema["items"]
|
||||
itype = None
|
||||
if "type" in items:
|
||||
itype = JSON_SCHEMA_TYPES_MAP.get(items["type"],
|
||||
items["type"])
|
||||
info["doc"] += "- Type: %s. " % itype
|
||||
if "description" in items:
|
||||
# add indention
|
||||
desc = items["description"].split("\n")
|
||||
info["doc"] += "\n ".join(desc)
|
||||
|
||||
new_schema = copy.copy(items)
|
||||
new_schema.pop("description", None)
|
||||
new_schema = json.dumps(new_schema, indent=4)
|
||||
new_schema = "\n ".join(
|
||||
new_schema.split("\n"))
|
||||
|
||||
info["doc"] += ("\n Format:\n\n"
|
||||
" .. code-block:: json\n\n"
|
||||
" %s\n" % new_schema)
|
||||
return info
|
||||
|
||||
elif isinstance(schema["type"], list):
|
||||
# it can be too complicated for parsing... do not do it deeply
|
||||
return {"doc": schema.get("description", ""),
|
||||
"type": "/".join(schema["type"])}
|
||||
|
||||
# dict
|
||||
elif schema["type"] == "object":
|
||||
info = {"doc": schema.get("description", ""),
|
||||
"type": "dict",
|
||||
"parameters": []}
|
||||
required_parameters = schema.get("required", [])
|
||||
if "properties" in schema:
|
||||
for name in schema["properties"]:
|
||||
if isinstance(schema["properties"][name], str):
|
||||
pinfo = {"name": name,
|
||||
"type": schema["properties"][name],
|
||||
"doc": ""}
|
||||
else:
|
||||
pinfo = process_jsonschema(schema["properties"][name])
|
||||
if name in required_parameters:
|
||||
pinfo["required"] = True
|
||||
pinfo["name"] = name
|
||||
info["parameters"].append(pinfo)
|
||||
elif "patternProperties" in schema:
|
||||
info.pop("parameters", None)
|
||||
info["patternProperties"] = []
|
||||
for k, v in schema["patternProperties"].items():
|
||||
info["patternProperties"].append(process_jsonschema(v))
|
||||
info["patternProperties"][-1]["name"] = k
|
||||
info["patternProperties"][-1]["type"] = "str"
|
||||
elif (not (set(schema.keys()) - {"type", "description", "$schema",
|
||||
"additionalProperties"})):
|
||||
# it is ok, schema accepts any object. nothing to add more
|
||||
pass
|
||||
elif "oneOf" in schema or "anyOf" in schema:
|
||||
# Example:
|
||||
# SCHEMA = {"type": "object", "$schema": consts.JSON_SCHEMA,
|
||||
# "oneOf": [{"properties": {"foo": {"type": "string"}}
|
||||
# "required": ["foo"],
|
||||
# "additionalProperties": False},
|
||||
# {"properties": {"bar": {"type": "string"}}
|
||||
# "required": ["bar"],
|
||||
# "additionalProperties": False},
|
||||
#
|
||||
schema_key = "oneOf" if "oneOf" in schema else "anyOf"
|
||||
schema_value = copy.deepcopy(schema.get(schema_key))
|
||||
|
||||
for item in schema_value:
|
||||
for k, v in schema.items():
|
||||
if k not in (schema_key, "description"):
|
||||
item[k] = v
|
||||
|
||||
return {
|
||||
"doc": schema.get("description", ""),
|
||||
"type": "dict",
|
||||
schema_key: [
|
||||
process_jsonschema(item) for item in schema_value]
|
||||
}
|
||||
else:
|
||||
raise Exception("Failed to parse jsonschema: %s" % schema)
|
||||
|
||||
if "definitions" in schema:
|
||||
info["definitions"] = schema["definitions"]
|
||||
return info
|
||||
else:
|
||||
raise Exception("Failed to parse jsonschema: %s" % schema)
|
||||
|
||||
# enum
|
||||
elif "enum" in schema:
|
||||
doc = schema.get("description", "")
|
||||
doc += "\nSet of expected values: '%s'." % ("', '".join(
|
||||
[e or "None" for e in schema["enum"]]))
|
||||
return {"doc": doc}
|
||||
|
||||
elif "anyOf" in schema:
|
||||
return {"doc": schema.get("description", ""),
|
||||
"anyOf": [process_jsonschema(i) for i in schema["anyOf"]]}
|
||||
|
||||
elif "oneOf" in schema:
|
||||
return {"doc": schema.get("description", ""),
|
||||
"oneOf": [process_jsonschema(i) for i in schema["oneOf"]]}
|
||||
|
||||
elif "$ref" in schema:
|
||||
return {"doc": schema.get("description", "n/a"),
|
||||
"ref": schema["$ref"]}
|
||||
else:
|
||||
raise Exception("Failed to parse jsonschema: %s" % schema)
|
||||
|
||||
|
||||
CATEGORIES = {
|
||||
"Common": ["OS Client"],
|
||||
"Deployment": ["Engine", "Provider Factory"],
|
||||
"Task Component": ["Chart", "Context", "Hook Action", "Hook Trigger",
|
||||
"Resource Type", "Task Exporter", "SLA", "Scenario",
|
||||
"Scenario Runner", "Trigger", "Validator"],
|
||||
"Verification Component": ["Verifier Context", "Verification Reporter",
|
||||
"Verifier Manager"]
|
||||
}
|
||||
|
||||
# NOTE(andreykurilin): several bases do not have docstings at all, so it is
|
||||
# redundant to display them
|
||||
IGNORED_BASES = ["Resource Type", "OS Client", "Exporters"]
|
||||
|
||||
|
||||
class PluginsReferenceDirective(rst.Directive):
|
||||
optional_arguments = 1
|
||||
option_spec = {"base_cls": str}
|
||||
|
||||
def _make_arg_items(self, items, ref_prefix, description=None,
|
||||
title="Parameters"):
|
||||
terms = []
|
||||
for item in items:
|
||||
iname = item.get("name", "") or item.pop("type")
|
||||
if "type" in item:
|
||||
iname += " (%s)" % item["type"]
|
||||
terms.append((iname, [item["doc"]]))
|
||||
return utils.make_definitions(title=title,
|
||||
ref_prefix=ref_prefix,
|
||||
terms=terms,
|
||||
descriptions=description)
|
||||
|
||||
def _make_plugin_section(self, plugin_cls, base_name=None):
|
||||
section_name = plugin_cls.get_name()
|
||||
if base_name:
|
||||
section_name += " [%s]" % base_name
|
||||
section_obj = utils.section(section_name)
|
||||
|
||||
info = plugin_cls.get_info()
|
||||
if info["title"]:
|
||||
section_obj.append(utils.paragraph(info["title"]))
|
||||
|
||||
if info["description"]:
|
||||
section_obj.extend(utils.parse_text(info["description"]))
|
||||
|
||||
if info["platform"]:
|
||||
section_obj.append(utils.paragraph(
|
||||
"**Platform**: %s" % info["platform"]))
|
||||
|
||||
if base_name:
|
||||
ref_prefix = "%s-%s-" % (base_name, plugin_cls.get_name())
|
||||
else:
|
||||
ref_prefix = "%s-" % plugin_cls.get_name()
|
||||
|
||||
if info["parameters"]:
|
||||
section_obj.extend(self._make_arg_items(info["parameters"],
|
||||
ref_prefix))
|
||||
|
||||
if info["returns"]:
|
||||
section_obj.extend(utils.parse_text(
|
||||
"**Returns**:\n%s" % info["returns"]))
|
||||
|
||||
if info["schema"]:
|
||||
schema = process_jsonschema(info["schema"])
|
||||
if "type" in schema:
|
||||
if "parameters" in schema:
|
||||
section_obj.extend(self._make_arg_items(
|
||||
items=schema["parameters"],
|
||||
ref_prefix=ref_prefix))
|
||||
elif "patternProperties" in schema:
|
||||
section_obj.extend(self._make_arg_items(
|
||||
items=schema["patternProperties"],
|
||||
ref_prefix=ref_prefix,
|
||||
description=["*Dictionary is expected. Keys should "
|
||||
"follow pattern(s) described bellow.*"]))
|
||||
elif "oneOf" in schema:
|
||||
section_obj.append(utils.note(
|
||||
"One of the following groups of "
|
||||
"parameters should be provided."))
|
||||
for i, oneOf in enumerate(schema["oneOf"], 1):
|
||||
description = None
|
||||
if oneOf.get("doc", None):
|
||||
description = [oneOf["doc"]]
|
||||
section_obj.extend(self._make_arg_items(
|
||||
items=oneOf["parameters"],
|
||||
ref_prefix=ref_prefix,
|
||||
title="Option %s of parameters" % i,
|
||||
description=description))
|
||||
else:
|
||||
section_obj.extend(self._make_arg_items(
|
||||
items=[schema], ref_prefix=ref_prefix))
|
||||
else:
|
||||
raise Exception("Failed to display provided schema: %s" %
|
||||
info["schema"])
|
||||
|
||||
if issubclass(plugin_cls, validation.ValidatablePluginMixin):
|
||||
validators = plugin_cls._meta_get("validators", default=[])
|
||||
platforms = [kwargs for name, args, kwargs in validators
|
||||
if name == "required_platform"]
|
||||
if platforms:
|
||||
section_obj.append(
|
||||
utils.paragraph("**Requires platform(s)**:"))
|
||||
section = ""
|
||||
for p in platforms:
|
||||
section += "* %s" % p["platform"]
|
||||
admin_msg = "credentials for admin user"
|
||||
user_msg = ("regular users (temporary users can be created"
|
||||
" via the 'users' context if admin user is "
|
||||
"specified for the platform)")
|
||||
if p.get("admin", False) and p.get("users", False):
|
||||
section += " with %s and %s." % (admin_msg, user_msg)
|
||||
elif p.get("admin", False):
|
||||
section += " with %s." % admin_msg
|
||||
elif p.get("users", False):
|
||||
section += " with %s." % user_msg
|
||||
section += "\n"
|
||||
|
||||
section_obj.extend(utils.parse_text(section))
|
||||
|
||||
filename = info["module"].replace(".", "/")
|
||||
ref = "https://github.com/openstack/rally/blob/master/%s.py" % filename
|
||||
section_obj.extend(utils.parse_text("**Module**:\n`%s`__\n\n__ %s"
|
||||
% (info["module"], ref)))
|
||||
return section_obj
|
||||
|
||||
def _make_plugin_base_section(self, base_cls, base_name=None):
|
||||
if base_name:
|
||||
title = ("%ss" % base_name if base_name[-1] != "y"
|
||||
else "%sies" % base_name[:-1])
|
||||
subcategory_obj = utils.subcategory(title)
|
||||
else:
|
||||
subcategory_obj = []
|
||||
for p in sorted(base_cls.get_all(), key=lambda o: o.get_name()):
|
||||
# do not display hidden contexts
|
||||
if p._meta_get("hidden", False):
|
||||
continue
|
||||
subcategory_obj.append(self._make_plugin_section(p, base_name))
|
||||
|
||||
return subcategory_obj
|
||||
|
||||
@staticmethod
|
||||
def _parse_class_name(cls):
|
||||
name = ""
|
||||
for word in re.split(r"([A-Z][a-z]*)", cls.__name__):
|
||||
if word:
|
||||
if len(word) > 1 and name:
|
||||
name += " "
|
||||
name += word
|
||||
return name
|
||||
|
||||
def _get_all_plugins_bases(self):
|
||||
"""Return grouped and sorted all plugins bases."""
|
||||
bases = []
|
||||
bases_names = []
|
||||
for p in discover.itersubclasses(plugin.Plugin):
|
||||
base_ref = getattr(p, "base_ref", None)
|
||||
if base_ref == p:
|
||||
name = self._parse_class_name(p)
|
||||
if name in bases_names:
|
||||
raise Exception("Two base classes with same name '%s' are "
|
||||
"detected." % name)
|
||||
bases_names.append(name)
|
||||
category_of_base = "Common"
|
||||
for cname, cbases in CATEGORIES.items():
|
||||
if name in cbases:
|
||||
category_of_base = cname
|
||||
|
||||
bases.append((category_of_base, name, p))
|
||||
return sorted(bases)
|
||||
|
||||
def run(self):
|
||||
plugins.load()
|
||||
bases = self._get_all_plugins_bases()
|
||||
if "base_cls" in self.options:
|
||||
for _category_name, base_name, base_cls in bases:
|
||||
if base_name == self.options["base_cls"]:
|
||||
return self._make_plugin_base_section(base_cls)
|
||||
raise Exception("Failed to generate plugins reference for '%s'"
|
||||
" plugin base." % self.options["base_cls"])
|
||||
|
||||
categories = {}
|
||||
|
||||
for category_name, base_name, base_cls in bases:
|
||||
# FIXME(andreykurilin): do not ignore anything
|
||||
if base_name in IGNORED_BASES:
|
||||
continue
|
||||
if category_name not in categories:
|
||||
categories[category_name] = utils.category(category_name)
|
||||
category_of_base = categories[category_name]
|
||||
category_of_base.append(self._make_plugin_base_section(base_cls,
|
||||
base_name))
|
||||
return [content for _name, content in sorted(categories.items())]
|
||||
|
||||
|
||||
def setup(app):
|
||||
plugins.load()
|
||||
app.add_directive("generate_plugin_reference", PluginsReferenceDirective)
|
@ -1,85 +0,0 @@
|
||||
# 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.
|
||||
|
||||
"""
|
||||
Docutils is awful library. Let's apply some hacks and aliases to simplify usage
|
||||
"""
|
||||
|
||||
from docutils import frontend
|
||||
from docutils import nodes
|
||||
from docutils.parsers import rst
|
||||
from docutils import utils
|
||||
import string
|
||||
|
||||
import six
|
||||
|
||||
|
||||
def parse_text(text):
|
||||
parser = rst.Parser()
|
||||
settings = frontend.OptionParser(
|
||||
components=(rst.Parser,)).get_default_values()
|
||||
document = utils.new_document(text, settings)
|
||||
parser.parse(text, document)
|
||||
return document.children
|
||||
|
||||
paragraph = lambda text: parse_text(text)[0]
|
||||
note = lambda msg: nodes.note("", paragraph(msg))
|
||||
hint = lambda msg: nodes.hint("", *parse_text(msg))
|
||||
warning = lambda msg: nodes.warning("", paragraph(msg))
|
||||
category = lambda title: parse_text("%s\n%s" % (title, "-" * len(title)))[0]
|
||||
subcategory = lambda title: parse_text("%s\n%s" % (title, "~" * len(title)))[0]
|
||||
section = lambda title: parse_text("%s\n%s" % (title, "\"" * len(title)))[0]
|
||||
|
||||
|
||||
def make_definition(term, ref, descriptions):
|
||||
"""Constructs definition with reference to it."""
|
||||
ref = ref.replace("_", "-").replace(" ", "-")
|
||||
definition = parse_text(
|
||||
".. _%(ref)s:\n\n* *%(term)s* [ref__]\n\n__ #%(ref)s" %
|
||||
{"ref": ref, "term": term})
|
||||
for descr in descriptions:
|
||||
if descr:
|
||||
if isinstance(descr, (six.text_type, six.binary_type)):
|
||||
if descr[0] not in string.ascii_uppercase:
|
||||
descr = descr.capitalize()
|
||||
descr = paragraph(" %s" % descr)
|
||||
definition.append(descr)
|
||||
return definition
|
||||
|
||||
|
||||
def make_definitions(title, ref_prefix, terms, descriptions=None):
|
||||
"""Constructs a list of definitions with reference to them."""
|
||||
raw_text = ["**%s**:" % title]
|
||||
if descriptions:
|
||||
for descr in descriptions:
|
||||
raw_text.append(descr)
|
||||
|
||||
for term, definitions in terms:
|
||||
ref = ("%s%s" % (ref_prefix, term)).lower().replace(
|
||||
".", "-").replace("_", "-").replace(" ", "-")
|
||||
raw_text.append(".. _%s:" % ref)
|
||||
raw_text.append("* *%s* [ref__]" % term)
|
||||
|
||||
for d in definitions:
|
||||
d = d.strip() if d else None
|
||||
if d:
|
||||
if d[0] not in string.ascii_uppercase:
|
||||
# .capitalize() removes existing caps
|
||||
d = d[0].upper() + d[1:]
|
||||
d = "\n ".join(d.split("\n"))
|
||||
raw_text.append(" %s" % d)
|
||||
|
||||
raw_text.append("__ #%s" % ref)
|
||||
|
||||
return parse_text("\n\n".join(raw_text) + "\n")
|
@ -1,11 +0,0 @@
|
||||
================
|
||||
Feature requests
|
||||
================
|
||||
|
||||
To request a new feature, you should create a document similar to other feature
|
||||
requests. And contribute it to this directory using the next instruction_.
|
||||
|
||||
If you don't have time to contribute your feature request via Gerrit, please
|
||||
contact Andrey Kurilin (andr.kurilin@gmail.com)
|
||||
|
||||
.. _instruction: http://rally.readthedocs.io/en/latest/contribute.html#how-to-contribute
|
@ -1,22 +0,0 @@
|
||||
==========================
|
||||
Capture Logs from services
|
||||
==========================
|
||||
|
||||
|
||||
Use case
|
||||
--------
|
||||
|
||||
A developer is executing various task and would like to capture logs as
|
||||
well as test results.
|
||||
|
||||
|
||||
Problem description
|
||||
-------------------
|
||||
|
||||
In case of errors it is quite hard to debug what happened.
|
||||
|
||||
|
||||
Possible solution
|
||||
-----------------
|
||||
|
||||
* Add special context that can capture the logs from tested services.
|
@ -1,23 +0,0 @@
|
||||
====================
|
||||
Check queue perfdata
|
||||
====================
|
||||
|
||||
Use case
|
||||
--------
|
||||
|
||||
Sometimes OpenStack services use common messaging system very prodigally. For
|
||||
example Neutron metering agent sending all database table data on new object
|
||||
creation i.e https://review.openstack.org/#/c/143672/. It cause to Neutron
|
||||
degradation and other obvious problems. It will be nice to have a way to track
|
||||
messages count and messages size in queue during tasks.
|
||||
|
||||
Problem description
|
||||
-------------------
|
||||
|
||||
Heavy usage of queue isn't checked.
|
||||
|
||||
Possible solution
|
||||
-----------------
|
||||
|
||||
* Before running task start process which will connect to queue
|
||||
topics and measure messages count, size and other data which we need.
|
@ -1,24 +0,0 @@
|
||||
=======================================
|
||||
Ability to compare results between task
|
||||
=======================================
|
||||
|
||||
|
||||
Use case
|
||||
--------
|
||||
|
||||
During the work on performance it's essential to be able to compare results of
|
||||
similar task before and after change in system.
|
||||
|
||||
|
||||
|
||||
Problem description
|
||||
-------------------
|
||||
|
||||
There is no command to compare two or more tasks and get tables and graphs.
|
||||
|
||||
|
||||
|
||||
Possible solution
|
||||
-----------------
|
||||
|
||||
* Add command that accepts 2 tasks UUID and prints graphs that compares result
|
@ -1,19 +0,0 @@
|
||||
===========================
|
||||
Distributed load generation
|
||||
===========================
|
||||
|
||||
Use Case
|
||||
--------
|
||||
|
||||
Some OpenStack projects (Marconi, MagnetoDB) require a real huge load,
|
||||
like 10-100k request per second for load testing.
|
||||
|
||||
To generate such huge load Rally has to create load from different
|
||||
servers.
|
||||
|
||||
Problem Description
|
||||
-------------------
|
||||
|
||||
* Rally can't generate load from different servers
|
||||
* Result processing can't handle big amount of data
|
||||
* There is no support for chunking results
|
@ -1,28 +0,0 @@
|
||||
===============================================
|
||||
Explicitly specify existing users for scenarios
|
||||
===============================================
|
||||
|
||||
|
||||
Use Case
|
||||
--------
|
||||
|
||||
Rally allows to reuse existing users for scenario runs. And we should be able
|
||||
to use only specified set of existing users for specific scenarios.
|
||||
|
||||
|
||||
Problem Description
|
||||
-------------------
|
||||
|
||||
For the moment if used `deployment` with existing users then Rally chooses
|
||||
user for each scenario run randomly. But there are cases when we may want
|
||||
to use one scenario with one user and another with different one specific user.
|
||||
Main reason for it is in different set of resources that each user has and
|
||||
those resources may be required for scenarios. Without this feature Rally user
|
||||
is forced to make all existing users similar and have all required resources
|
||||
set up for all scenarios he uses. But it is redundant.
|
||||
|
||||
|
||||
Possible solution
|
||||
-----------------
|
||||
|
||||
* Make it possible to use explicitly existing_users context
|
@ -1,26 +0,0 @@
|
||||
===========================
|
||||
Historical performance data
|
||||
===========================
|
||||
|
||||
|
||||
Use case
|
||||
--------
|
||||
|
||||
OpenStack is really rapidly developed. Hundreds of patches are merged daily
|
||||
and it's really hard to track how performance is changed during time.
|
||||
It will be nice to have a way to track performance of major functionality
|
||||
of OpenStack running periodically rally task and building graphs that represent
|
||||
how performance of specific method is changed during the time.
|
||||
|
||||
|
||||
Problem description
|
||||
-------------------
|
||||
|
||||
There is no way to bind tasks
|
||||
|
||||
|
||||
Possible solution
|
||||
-----------------
|
||||
|
||||
* Add grouping for tasks
|
||||
* Add command that creates historical graphs
|
@ -1,33 +0,0 @@
|
||||
==========================================
|
||||
Support testing clouds that are using LDAP
|
||||
==========================================
|
||||
|
||||
Use Case
|
||||
--------
|
||||
|
||||
A lot of production clouds are using LDAP with read only access. It means
|
||||
that load can be generated only by existing in system users and there is no
|
||||
admin access.
|
||||
|
||||
|
||||
Problem Description
|
||||
-------------------
|
||||
|
||||
Rally is using admin access to create temporary users that will be used to
|
||||
produce load.
|
||||
|
||||
|
||||
Possible Solution
|
||||
-----------------
|
||||
|
||||
* Add some way to pass already existing users
|
||||
|
||||
|
||||
Current Solution
|
||||
----------------
|
||||
|
||||
* Add ability to specify existing users in the *ExistingCloud* plugin config
|
||||
* When such an *ExistingCloud* deployment is active, and the task file does not
|
||||
specify the *"users"* context, use the existing users instead of creating the
|
||||
temporary ones.
|
||||
* Modify the *rally show* commands to list resources for each user separately.
|
@ -1,24 +0,0 @@
|
||||
========================================
|
||||
Running Tempest using custom concurrency
|
||||
========================================
|
||||
|
||||
|
||||
Use case
|
||||
--------
|
||||
|
||||
User might want to use specific concurrency for running tests based on his
|
||||
deployment and available resources.
|
||||
|
||||
|
||||
Problem description
|
||||
-------------------
|
||||
|
||||
"rally verify start" command does not allow to specify concurrency
|
||||
for tempest tests. And they always run using concurrency equal
|
||||
to amount of CPU cores.
|
||||
|
||||
|
||||
Possible solution
|
||||
-----------------
|
||||
|
||||
* Add ``--concurrency`` option to "rally verify start" command.
|
@ -1,58 +0,0 @@
|
||||
==================================
|
||||
Stop scenario after several errors
|
||||
==================================
|
||||
|
||||
|
||||
Use case
|
||||
--------
|
||||
|
||||
Starting long tests on the big environments.
|
||||
|
||||
|
||||
Problem description
|
||||
-------------------
|
||||
|
||||
When we start a rally scenario on the env where keystone dies we get a lot of
|
||||
time before timeout happens.
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
Times in hard tests
|
||||
05:25:40 rally-scenarios.cinder
|
||||
05:25:40 create-and-delete-volume [4074 iterations, 15 threads] OK 8.91
|
||||
08:00:02 create-and-delete-snapshot [5238 iterations, 15 threads] OK 17.46
|
||||
08:53:20 create-and-list-volume [4074 iterations, 15 threads] OK 3.18
|
||||
12:04:14 create-snapshot-and-attach-volume [2619 iterations, 15 threads] FAIL
|
||||
14:18:44 create-and-attach-volume [2619 iterations, 15 threads] FAIL
|
||||
14:23:47 rally-scenarios.vm
|
||||
14:23:47 boot_runcommand_metadata_delete [5 iterations, 5 threads] FAIL
|
||||
16:30:46 rally-scenarios.nova
|
||||
16:30:46 boot_and_list_server [5820 iterations, 15 threads] FAIL
|
||||
19:19:30 resize_server [5820 iterations, 15 threads] FAIL
|
||||
02:51:13 boot_and_delete_server_with_secgroups [5820 iterations, 60 threads] FAIL
|
||||
|
||||
|
||||
Times in light variant
|
||||
00:38:25 rally-scenarios.cinder
|
||||
00:38:25 create-and-delete-volume [14 iterations, 1 threads] OK 5.30
|
||||
00:40:39 create-and-delete-snapshot [18 iterations, 1 threads] OK 5.65
|
||||
00:41:52 create-and-list-volume [14 iterations, 1 threads] OK 2.89
|
||||
00:45:18 create-snapshot-and-attach-volume [9 iterations, 1 threads] OK 17.75
|
||||
00:48:54 create-and-attach-volume [9 iterations, 1 threads] OK 20.04
|
||||
00:52:29 rally-scenarios.vm
|
||||
00:52:29 boot_runcommand_metadata_delete [5 iterations, 5 threads] OK 128.86
|
||||
00:56:42 rally-scenarios.nova
|
||||
00:56:42 boot_and_list_server [20 iterations, 1 threads] OK 6.98
|
||||
01:04:48 resize_server [20 iterations, 1 threads] OK 22.90
|
||||
|
||||
|
||||
In the hard test we have a lot of timeouts from keystone and a lot of time on
|
||||
test execution
|
||||
|
||||
Possible solution
|
||||
-----------------
|
||||
|
||||
Improve SLA check functionality to work "online". And add ability to control
|
||||
execution process and stop load generation in case of sla check failures.
|
||||
|
@ -1,26 +0,0 @@
|
||||
======================================================================
|
||||
Enhancements to installation script: ``--version`` and ``--uninstall``
|
||||
======================================================================
|
||||
|
||||
|
||||
Use case
|
||||
--------
|
||||
|
||||
User might wish to control which rally version is installed or even purge
|
||||
rally from the machine completely.
|
||||
|
||||
|
||||
Problem description
|
||||
-------------------
|
||||
|
||||
#. Installation script doesn't allow to choose version.
|
||||
#. No un-install support.
|
||||
|
||||
|
||||
|
||||
Possible solution
|
||||
-----------------
|
||||
|
||||
#. Add ``--version`` option to installation script.
|
||||
#. Add ``--uninstall`` option to installation script or create an
|
||||
un-installation script
|
@ -1,26 +0,0 @@
|
||||
==================================================================================
|
||||
Installation script: ``--pypi-mirror``, ``--package-mirror`` and ``--venv-mirror``
|
||||
==================================================================================
|
||||
|
||||
|
||||
Use case
|
||||
--------
|
||||
|
||||
Installation is pretty easy when there is an Internet connection available.
|
||||
And there is surely a number of OpenStack uses when whole environment is
|
||||
isolated. In this case, we need somehow specify where installation script
|
||||
should take required libs and packages.
|
||||
|
||||
|
||||
Problem description
|
||||
-------------------
|
||||
|
||||
#. Installation script can't work without direct Internet connection
|
||||
|
||||
|
||||
Possible solution #1
|
||||
--------------------
|
||||
|
||||
#. Add ``--pypi-mirror`` option to installation script.
|
||||
#. Add ``--package-mirror`` option to installation script.
|
||||
#. Add ``--venv-mirror`` option to installation script.
|
@ -1,27 +0,0 @@
|
||||
=======================
|
||||
Launch Specific SubTask
|
||||
=======================
|
||||
|
||||
|
||||
Use case
|
||||
--------
|
||||
|
||||
A developer is working on a feature that is covered by one or more specific
|
||||
subtask. He/she would like to execute a rally task with an
|
||||
existing task template file (YAML or JSON) indicating exactly what subtask
|
||||
will be executed.
|
||||
|
||||
|
||||
Problem description
|
||||
-------------------
|
||||
|
||||
When executing a task with a template file in Rally, all subtasks are
|
||||
executed without the ability to specify one or a set of subtasks the user
|
||||
would like to execute.
|
||||
|
||||
|
||||
Possible solution
|
||||
-----------------
|
||||
|
||||
* Add optional flag to rally task start command to specify one or more
|
||||
subtasks to execute as part of that test run.
|
@ -1,35 +0,0 @@
|
||||
======================================
|
||||
Using multi scenarios to generate load
|
||||
======================================
|
||||
|
||||
|
||||
Use Case
|
||||
--------
|
||||
|
||||
Rally should be able to generate real life load. Simultaneously create load
|
||||
on different components of OpenStack, e.g. simultaneously booting VM, uploading
|
||||
image and listing users.
|
||||
|
||||
|
||||
Problem Description
|
||||
-------------------
|
||||
|
||||
At the moment Rally is able to run only 1 scenario per subtask.
|
||||
Scenario are quite specific (e.g. boot and delete VM for example) and can't
|
||||
actually generate real life load.
|
||||
|
||||
Writing a lot of specific subtask scenarios that produces more real life
|
||||
load will produce mess and a lot of duplication of code.
|
||||
|
||||
|
||||
Possible solution
|
||||
-----------------
|
||||
|
||||
* Extend Rally subtask configuration in such way to support passing
|
||||
multiple scenarios in single subtask context
|
||||
|
||||
* Extend Rally task output format to support results of multiple scenarios in
|
||||
single subtask separately.
|
||||
|
||||
* Extend rally task plot2html and rally task detailed to show results
|
||||
separately for every scenario.
|
@ -1,20 +0,0 @@
|
||||
======================
|
||||
Multiple attach volume
|
||||
======================
|
||||
|
||||
|
||||
Use Case
|
||||
--------
|
||||
Since multiple volume attaching support to OpenStack Mitaka, one volume can be
|
||||
attached to several instances or hosts, Rally should add scenarios about
|
||||
multiple attach volume.
|
||||
|
||||
|
||||
Problem Description
|
||||
-------------------
|
||||
Rally lack of scenarios about multiple attach volume.
|
||||
|
||||
|
||||
Possible solution
|
||||
-----------------
|
||||
* Add nova scenarios "multi_attach_volume" and "multi_detach_volume"
|
@ -1,40 +0,0 @@
|
||||
===========================================
|
||||
Add support of persistence task environment
|
||||
===========================================
|
||||
|
||||
Use Case
|
||||
--------
|
||||
|
||||
There are situations when same environment is used across different tasks.
|
||||
For example you would like to improve operation of listing objects.
|
||||
For example:
|
||||
|
||||
- Create hundreds of objects
|
||||
- Collect baseline of list performance
|
||||
- Fix something in system
|
||||
- Repeat the performance test
|
||||
- Repeat fixing and testing until things are fixed.
|
||||
|
||||
Current implementation of Rally will force you to recreate task context which
|
||||
is time consuming operation.
|
||||
|
||||
|
||||
Problem Description
|
||||
-------------------
|
||||
|
||||
Fortunately Rally has already a mechanism for creating task environment via
|
||||
contexts. Unfortunately it's atomic operation:
|
||||
- Create task context
|
||||
- Perform subtask scenario-runner pairs
|
||||
- Destroy task context
|
||||
|
||||
This should be split to 3 separated steps.
|
||||
|
||||
|
||||
Possible solution
|
||||
-----------------
|
||||
|
||||
* Add new CLI operations to work with task environment:
|
||||
(show, create, delete, list)
|
||||
|
||||
* Allow task to start against existing task context (instead of deployment)
|
@ -1,36 +0,0 @@
|
||||
========================
|
||||
Production read cleanups
|
||||
========================
|
||||
|
||||
Use Case
|
||||
--------
|
||||
|
||||
Rally should delete in all cases all resources that it creates during tasks.
|
||||
|
||||
|
||||
Problem Description
|
||||
-------------------
|
||||
|
||||
* (implemented) Deletion rate limit
|
||||
|
||||
You can kill cloud by deleting too many objects simultaneously, so deletion
|
||||
rate limit is required
|
||||
|
||||
* (implemented) Retry on failures
|
||||
|
||||
There should be few attempts to delete resource in case of failures
|
||||
|
||||
* (implemented) Log resources that failed to be deleted
|
||||
|
||||
We should log warnings about all non deleted resources. This information
|
||||
should include UUID of resource, it's type and project.
|
||||
|
||||
* (implemented) Pluggable
|
||||
|
||||
It should be simple to add new cleanups adding just plugins somewhere.
|
||||
|
||||
* Disaster recovery
|
||||
|
||||
Rally should use special name patterns, to be able to delete resources
|
||||
in such case if something went wrong with server that is running Rally. And
|
||||
you have just new instance (without old Rally DB) of Rally on new server.
|
@ -1,177 +0,0 @@
|
||||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = _build
|
||||
|
||||
# User-friendly check for sphinx-build
|
||||
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
|
||||
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
|
||||
endif
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
# the i18n builder cannot share the environment and doctrees with the others
|
||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " texinfo to make Texinfo files"
|
||||
@echo " info to make Texinfo files and run them through makeinfo"
|
||||
@echo " gettext to make PO message catalogs"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " xml to make Docutils-native XML files"
|
||||
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILDDIR)/*
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/rally.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/rally.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/rally"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/rally"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
latexpdfja:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through platex and dvipdfmx..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
texinfo:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo
|
||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||
"(use \`make info' here to do that automatically)."
|
||||
|
||||
info:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo "Running Texinfo files through makeinfo..."
|
||||
make -C $(BUILDDIR)/texinfo info
|
||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||
|
||||
gettext:
|
||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||
@echo
|
||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
||||
|
||||
xml:
|
||||
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
|
||||
@echo
|
||||
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
|
||||
|
||||
pseudoxml:
|
||||
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
|
||||
@echo
|
||||
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
|
@ -1,3 +0,0 @@
|
||||
.body img {
|
||||
max-width: 100%;
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
{% extends "openstack/layout.html" %}
|
||||
{% set show_source = False %}
|
||||
{% set css_files = css_files + ["_static/img.css"] %}
|
||||
|
||||
{# sidebarlogo is a top block in sidebar. Let's use it to display home link #}
|
||||
{%- block sidebarlogo %}
|
||||
<h3><a href="{{ pathto(master_doc) }}">What is Rally?</a></h3>
|
||||
{%- endblock %}
|
||||
|
||||
{# Display global toc instead of local #}
|
||||
{%- block sidebartoc %}
|
||||
<h3>Contents</h3>
|
||||
{{ toctree() }}
|
||||
{%- endblock %}
|
||||
|
||||
{# Turn off sections "Previous topic" and "Next topic" #}
|
||||
{%- block sidebarrel %}{% endblock %}
|
||||
|
||||
{% block projectsource %}
|
||||
<h3>Contacts</h3>
|
||||
<p class="topless" style="color: black">
|
||||
<b>IRC</b> <br /><a href="ircs://irc.freenode.net:6697/#openstack-rally">#openstack-rally</a> channel at FreeNode<br />
|
||||
<b>E-mail</b> <br /><a href="mailto:openstack-dev@lists.openstack.org?subject=[Rally]">openstack-dev@lists.openstack.org</a> with "[Rally]" tag in subject
|
||||
</p>
|
||||
<h3>Useful links</h3>
|
||||
<ul>
|
||||
<li><a href="{{ pathto(master_doc) }}">Documentation</a></li>
|
||||
<li><a href="http://rally.readthedocs.org/en/latest/">Documentation at RTD</a></li>
|
||||
<li><a href="http://git.openstack.org/cgit/openstack/rally">Source</a></li>
|
||||
<li><a href="https://github.com/openstack/rally">GitHub mirror</a></li>
|
||||
<li><a href="http://bugs.launchpad.net/rally">Bug tracker</a></li>
|
||||
<li><a href="https://docs.google.com/a/mirantis.com/spreadsheets/d/16DXpfbqvlzMFaqaXAcJsBzzpowb_XpymaK2aFY2gA2g">RoadMap</a></li>
|
||||
<li><a href="https://launchpad.net/rally">Launchpad page</a></li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
{# copy-pasted from original theme and extended with Rally links #}
|
||||
{%- block header_navigation %}
|
||||
<li><a href="http://www.openstack.org/" title="Go to the Home page" class="link">Home</a></li>
|
||||
<li><a href="http://www.openstack.org/projects/" title="Go to the Projects page">Projects</a></li>
|
||||
<li><a href="http://www.openstack.org/user-stories/" title="Go to the User Stories page" class="link">User Stories</a></li>
|
||||
<li><a href="http://www.openstack.org/community/" title="Go to the Community page" class="link">Community</a></li>
|
||||
<li><a href="http://www.openstack.org/blog/" title="Go to the OpenStack Blog">Blog</a></li>
|
||||
<li><a href="http://wiki.openstack.org/" title="Go to the OpenStack Wiki">Wiki</a></li>
|
||||
<li><a href="{{ pathto(master_doc) }}" title="Go to Rally Documentation" class="current">Documentation</a></li>
|
||||
{% endblock %}
|
||||
|
@ -1,2 +0,0 @@
|
||||
[theme]
|
||||
inherit = openstack
|
@ -1,11 +0,0 @@
|
||||
.. _cli-reference:
|
||||
|
||||
|
||||
Command Line Interface
|
||||
======================
|
||||
|
||||
.. contents::
|
||||
:depth: 1
|
||||
:local:
|
||||
|
||||
.. make_cli_reference::
|
@ -1,299 +0,0 @@
|
||||
# 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.
|
||||
#
|
||||
# Rally documentation build configuration file, created by
|
||||
# sphinx-quickstart on Fri Jan 10 23:19:18 2014.
|
||||
#
|
||||
# This file is execfile() with the current directory set to its containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# auto-generated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import datetime as dt
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import rally.common.version
|
||||
|
||||
# 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.extend([
|
||||
# os.path.abspath("../.."),
|
||||
# os.path.abspath("../"),
|
||||
# os.path.abspath("./")
|
||||
# ])
|
||||
|
||||
sys.path.insert(0, os.path.abspath("../../"))
|
||||
sys.path.insert(0, os.path.abspath("../"))
|
||||
sys.path.insert(0, os.path.abspath("./"))
|
||||
|
||||
|
||||
# -- General configuration ----------------------------------------------------
|
||||
|
||||
on_rtd = os.environ.get("READTHEDOCS") == "True"
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
# needs_sphinx = "1.0"
|
||||
|
||||
# Add any Sphinx extension module names here, as strings.
|
||||
# They can be extensions coming with Sphinx (named "sphinx.ext.*") or your
|
||||
# custom ones.
|
||||
extensions = [
|
||||
"sphinx.ext.autodoc",
|
||||
"sphinx.ext.doctest",
|
||||
"sphinx.ext.todo",
|
||||
"sphinx.ext.coverage",
|
||||
"sphinx.ext.ifconfig",
|
||||
"sphinx.ext.viewcode",
|
||||
"ext.cli_reference",
|
||||
"ext.plugin_reference",
|
||||
"ext.include_vars"
|
||||
]
|
||||
todo_include_todos = True
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ["_templates"]
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = ".rst"
|
||||
|
||||
# The encoding of source files.
|
||||
# source_encoding = "utf-8-sig"
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = "index"
|
||||
|
||||
# General information about the project.
|
||||
project = u"Rally"
|
||||
copyright = u"%d, OpenStack Foundation" % dt.datetime.now().year
|
||||
|
||||
# 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.
|
||||
#
|
||||
# The short X.Y version.
|
||||
|
||||
|
||||
version = rally.common.version.version_string()
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = rally.common.version.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"
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = [
|
||||
"feature_request/README.rst",
|
||||
"samples/README.rst",
|
||||
"**/README.rst"
|
||||
]
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents
|
||||
# default_role = None
|
||||
|
||||
# If true, "()" will be appended to :func: etc. cross-reference text.
|
||||
add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
# show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = "sphinx"
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
# modindex_common_prefix = []
|
||||
|
||||
|
||||
# -- Options for HTML output --------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
if not on_rtd:
|
||||
html_theme = "openstackrally"
|
||||
else:
|
||||
html_theme = "default"
|
||||
# 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.
|
||||
if not on_rtd:
|
||||
import oslosphinx
|
||||
theme_dir = os.path.join(os.path.dirname(oslosphinx.__file__), "theme")
|
||||
html_theme_path = [theme_dir, "_templates"]
|
||||
else:
|
||||
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".
|
||||
if not on_rtd:
|
||||
html_static_path = ["_templates/openstackrally/_static"]
|
||||
else:
|
||||
html_static_path = []
|
||||
|
||||
# If not "", a "Last updated on:" timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
git_cmd = [
|
||||
"git", "log", "--pretty=format:'%ad, commit %h'", "--date=local", "-n1"]
|
||||
html_last_updated_fmt = subprocess.check_output(git_cmd).decode("utf-8")
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
html_use_smartypants = False
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
html_sidebars = {"**": ["searchbox.html", "globaltoc.html"]}
|
||||
|
||||
# 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_domain_indices = 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, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
# html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
# html_show_copyright = 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 = ""
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
# html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = "%sdoc" % project
|
||||
|
||||
|
||||
# -- Options for LaTeX output -------------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ("letterpaper" or "a4paper").
|
||||
# "papersize": "letterpaper",
|
||||
# The font size ("10pt", "11pt" or "12pt").
|
||||
# "pointsize": "10pt",
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
# "preamble": "",
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual])
|
||||
latex_documents = [
|
||||
("index",
|
||||
"%s.tex" % project,
|
||||
u"%s Documentation" % project,
|
||||
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
|
||||
|
||||
# If true, show page references after internal links.
|
||||
# latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
# latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
# latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
# latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output -------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
# man_pages = [
|
||||
# ("index", "rally", u"Rally Documentation",
|
||||
# [u"Rally Team"], 1)
|
||||
# ]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
# man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output -----------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
("index", "Rally", u"Rally Documentation",
|
||||
u"Rally Team", "Rally",
|
||||
"Testing framework and tool for all kinds of tests",
|
||||
"Development"),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
# texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
# texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: "footnote", "no", or "inline".
|
||||
# texinfo_show_urls = "footnote"
|
@ -1,261 +0,0 @@
|
||||
..
|
||||
Copyright 2015 Mirantis Inc. 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.
|
||||
|
||||
.. _contribute:
|
||||
|
||||
Contribute to Rally
|
||||
===================
|
||||
|
||||
Where to begin
|
||||
--------------
|
||||
|
||||
Please take a look `our Roadmap`_ to get information about our current work
|
||||
directions.
|
||||
|
||||
In case you have questions or want to share your ideas, be sure to contact us
|
||||
either at `Rally-dev/Lobby`_ channel on **Gitter** messenger (or, less
|
||||
preferably, at the ``#openstack-rally`` IRC channel on **irc.freenode.net**).
|
||||
|
||||
If you are going to contribute to Rally, you will probably need to grasp a
|
||||
better understanding of several main design concepts used throughout our
|
||||
project (such as **scenarios**, **contexts** etc.). To do so, please
|
||||
read :ref:`this article <main_concepts>`.
|
||||
|
||||
|
||||
How to contribute
|
||||
-----------------
|
||||
|
||||
1. You need a `Launchpad`_ account and need to be joined to the
|
||||
`OpenStack team`_. You can also join the `Rally team`_ if you want to. Make
|
||||
sure Launchpad has your SSH key, Gerrit (the code review system) uses this.
|
||||
|
||||
2. Sign the CLA as outlined in the `account setup`_ section of the developer
|
||||
guide.
|
||||
|
||||
3. Tell git your details:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git config --global user.name "Firstname Lastname"
|
||||
git config --global user.email "your_email@youremail.com"
|
||||
|
||||
4. Install git-review. This tool takes a lot of the pain out of remembering
|
||||
commands to push code up to Gerrit for review and to pull it back down to edit
|
||||
it. It is installed using:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pip install git-review
|
||||
|
||||
Several Linux distributions (notably Fedora 16 and Ubuntu 12.04) are also
|
||||
starting to include git-review in their repositories so it can also be
|
||||
installed using the standard package manager.
|
||||
|
||||
5. Grab the Rally repository:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git clone git@github.com:openstack/rally.git
|
||||
|
||||
6. Checkout a new branch to hack on:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git checkout -b TOPIC-BRANCH
|
||||
|
||||
7. Start coding
|
||||
|
||||
8. Run the test suite locally to make sure nothing broke, e.g. (this will run
|
||||
py34/py27/pep8 tests):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
tox
|
||||
|
||||
**(NOTE: you should have installed tox<=1.6.1)**
|
||||
|
||||
If you extend Rally with new functionality, make sure you have also provided
|
||||
unit and/or functional tests for it.
|
||||
|
||||
9. Commit your work using:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git commit -a
|
||||
|
||||
|
||||
Make sure you have supplied your commit with a neat commit message, containing
|
||||
a link to the corresponding blueprint / bug, if appropriate.
|
||||
|
||||
10. Push the commit up for code review using:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git review -R
|
||||
|
||||
That is the awesome tool we installed earlier that does a lot of hard work for
|
||||
you.
|
||||
|
||||
11. Watch your email or `review site`_, it will automatically send your code
|
||||
for a battery of tests on our `Jenkins setup`_ and the core team for the
|
||||
project will review your code. If there are any changes that should be made
|
||||
they will let you know.
|
||||
|
||||
12. When all is good the review site will automatically merge your code.
|
||||
|
||||
|
||||
(This tutorial is based on:
|
||||
http://www.linuxjedi.co.uk/2012/03/real-way-to-start-hacking-on-openstack.html)
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
Please, don't hesitate to write tests ;)
|
||||
|
||||
|
||||
Unit tests
|
||||
^^^^^^^^^^
|
||||
|
||||
*Files: /tests/unit/**
|
||||
|
||||
The goal of unit tests is to ensure that internal parts of the code work
|
||||
properly. All internal methods should be fully covered by unit tests with a
|
||||
reasonable mocks usage.
|
||||
|
||||
|
||||
About Rally unit tests:
|
||||
|
||||
- All `unit tests`_ are located inside /tests/unit/*
|
||||
- Tests are written on top of: *testtools* and *mock* libs
|
||||
- `Tox`_ is used to run unit tests
|
||||
|
||||
|
||||
To run unit tests locally:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ pip install tox
|
||||
$ tox
|
||||
|
||||
To run py34, py27 or pep8 only:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ tox -e <name>
|
||||
|
||||
#NOTE: <name> is one of py34, py27 or pep8
|
||||
|
||||
To run a single unit test e.g. test_deployment
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ tox -e <name> -- <test_name>
|
||||
|
||||
#NOTE: <name> is one of py34, py27 or pep8
|
||||
# <test_name> is the unit test case name, e.g tests.unit.test_osclients
|
||||
|
||||
To debug issues on the unit test:
|
||||
|
||||
- Add breakpoints on the test file using ``import pdb;`` ``pdb.set_trace()``
|
||||
- Then run tox in debug mode:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ tox -e debug <test_name>
|
||||
#NOTE: use python 2.7
|
||||
#NOTE: <test_name> is the unit test case name
|
||||
|
||||
or
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ tox -e debug34 <test_name>
|
||||
#NOTE: use python 3.4
|
||||
#NOTE: <test_name> is the unit test case name
|
||||
|
||||
To get test coverage:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ tox -e cover
|
||||
|
||||
#NOTE: Results will be in /cover/index.html
|
||||
|
||||
To generate docs:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ tox -e docs
|
||||
|
||||
#NOTE: Documentation will be in doc/source/_build/html/index.html
|
||||
|
||||
Functional tests
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
*Files: /tests/functional/**
|
||||
|
||||
The goal of `functional tests`_ is to check that everything works well
|
||||
together. Functional tests use Rally API only and check responses without
|
||||
touching internal parts.
|
||||
|
||||
To run functional tests locally:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ source openrc
|
||||
$ rally deployment create --fromenv --name testing
|
||||
$ tox -e cli
|
||||
|
||||
#NOTE: openrc file with OpenStack admin credentials
|
||||
|
||||
Output of every Rally execution will be collected under some reports root in
|
||||
directory structure like: reports_root/ClassName/MethodName_suffix.extension
|
||||
This functionality implemented in tests.functional.utils.Rally.__call__ method.
|
||||
Use 'gen_report_path' method of 'Rally' class to get automatically generated
|
||||
file path and name if you need. You can use it to publish html reports,
|
||||
generated during tests. Reports root can be passed throw environment variable
|
||||
'REPORTS_ROOT'. Default is 'rally-cli-output-files'.
|
||||
|
||||
Rally CI scripts
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
*Files: /tests/ci/**
|
||||
|
||||
This directory contains scripts and files related to the Rally CI system.
|
||||
|
||||
Rally Style Commandments
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
*Files: /tests/hacking/*
|
||||
|
||||
This module contains Rally specific hacking rules for checking commandments.
|
||||
|
||||
For more information about Style Commandments, read the
|
||||
`OpenStack Style Commandments manual`_.
|
||||
|
||||
.. references:
|
||||
|
||||
.. _our Roadmap: https://docs.google.com/a/mirantis.com/spreadsheets/d/16DXpfbqvlzMFaqaXAcJsBzzpowb_XpymaK2aFY2gA2g/edit#gid=0
|
||||
.. _Rally-dev/Lobby: https://gitter.im/rally-dev/Lobby
|
||||
.. _Launchpad: https://launchpad.net/
|
||||
.. _OpenStack team: https://launchpad.net/openstack
|
||||
.. _Rally team: https://launchpad.net/rally
|
||||
.. _account setup: https://docs.openstack.org/infra/manual/developers.html#development-workflow
|
||||
.. _review site: https://review.openstack.org/
|
||||
.. _Jenkins setup: http://jenkins.openstack.org/
|
||||
.. _unit tests: http://en.wikipedia.org/wiki/Unit_testing
|
||||
.. _Tox: https://tox.readthedocs.org/en/latest/
|
||||
.. _functional tests: https://en.wikipedia.org/wiki/Functional_testing
|
||||
.. _OpenStack Style Commandments manual: https://docs.openstack.org/hacking/latest/
|
@ -1 +0,0 @@
|
||||
../feature_request/
|
@ -1,34 +0,0 @@
|
||||
..
|
||||
Copyright 2015 Mirantis Inc. 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.
|
||||
|
||||
.. _feature_requests:
|
||||
|
||||
Request New Features
|
||||
====================
|
||||
|
||||
To request a new feature, you should create a document similar to other feature
|
||||
requests and then contribute it to the **doc/feature_request** directory of the
|
||||
Rally repository (see the :ref:`How-to-contribute tutorial <contribute>`).
|
||||
|
||||
If you don't have time to contribute your feature request via Gerrit, please
|
||||
contact Boris Pavlovic (boris@pavlovic.me)
|
||||
|
||||
Active feature requests:
|
||||
|
||||
.. toctree::
|
||||
:glob:
|
||||
:maxdepth: 1
|
||||
|
||||
feature_request/*
|
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 94 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 124 KiB |
Before Width: | Height: | Size: 172 KiB |
Before Width: | Height: | Size: 164 KiB |
Before Width: | Height: | Size: 103 KiB |
Before Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 114 KiB |
Before Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 116 KiB |
Before Width: | Height: | Size: 131 KiB |
Before Width: | Height: | Size: 184 KiB |
Before Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 109 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 101 KiB |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 99 KiB |
Before Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 81 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 73 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 73 KiB |
Before Width: | Height: | Size: 9.6 KiB |
Before Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 131 KiB |
@ -1,48 +0,0 @@
|
||||
..
|
||||
Copyright 2015 Mirantis Inc. 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.
|
||||
|
||||
==============
|
||||
What is Rally?
|
||||
==============
|
||||
|
||||
**OpenStack** is, undoubtedly, a really *huge* ecosystem of cooperative
|
||||
services. **Rally** is a **testing tool** that answers the question:
|
||||
**"How does OpenStack work at scale?"**. To make this possible, Rally
|
||||
**automates** and **unifies** multi-node OpenStack deployment, cloud
|
||||
verification, testing & profiling. Rally does it in a **generic** way,
|
||||
making it possible to check whether OpenStack is going to work well on, say, a
|
||||
1k-servers installation under high load. Thus it can be used as a basic tool
|
||||
for an *OpenStack CI/CD system* that would continuously improve its SLA,
|
||||
performance and stability.
|
||||
|
||||
.. image:: ./images/Rally-Actions.png
|
||||
:align: center
|
||||
|
||||
|
||||
Contents
|
||||
========
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
overview/index
|
||||
install_and_upgrade/index
|
||||
quick_start/index
|
||||
cli_reference
|
||||
task/index
|
||||
verification/index
|
||||
plugins/index
|
||||
contribute
|
||||
feature_requests
|
||||
project_info/index
|
@ -1 +0,0 @@
|
||||
../../../rally/common/db/sqlalchemy/migrations/README.rst
|
@ -1,24 +0,0 @@
|
||||
..
|
||||
Copyright 2015 Mirantis Inc. 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.
|
||||
|
||||
=========================
|
||||
Installation and upgrades
|
||||
=========================
|
||||
|
||||
.. toctree::
|
||||
:glob:
|
||||
|
||||
install
|
||||
db_migrations
|
@ -1,182 +0,0 @@
|
||||
..
|
||||
Copyright 2015 Mirantis Inc. 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.
|
||||
|
||||
.. _install:
|
||||
|
||||
Installation process
|
||||
====================
|
||||
|
||||
Automated installation
|
||||
----------------------
|
||||
|
||||
The easiest way to install Rally is by executing its `installation script`_
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
wget -q -O- https://raw.githubusercontent.com/openstack/rally/master/install_rally.sh | bash
|
||||
# or using curl
|
||||
curl https://raw.githubusercontent.com/openstack/rally/master/install_rally.sh | bash
|
||||
|
||||
The installation script will also check if all the software required
|
||||
by Rally is already installed in your system; if run as **root** user
|
||||
and some dependency is missing it will ask you if you want to install
|
||||
the required packages.
|
||||
|
||||
By default it will install Rally in a virtualenv in ``~/rally`` when
|
||||
run as standard user, or install system wide when run as root. You can
|
||||
install Rally in a **venv** by using the option ``--target``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
./install_rally.sh --target /foo/bar
|
||||
|
||||
You can also install Rally system wide by running script as root and
|
||||
without ``--target`` option:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo ./install_rally.sh
|
||||
|
||||
|
||||
Run ``./install_rally.sh`` with option ``--help`` to have a list of all
|
||||
available options:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ ./install_rally.sh --help
|
||||
Usage: install_rally.sh [options]
|
||||
|
||||
This script will install rally either in the system (as root) or in a virtual environment.
|
||||
|
||||
Options:
|
||||
-h, --help Print this help text
|
||||
-v, --verbose Verbose mode
|
||||
-s, --system Install system-wide.
|
||||
-d, --target DIRECTORY Install Rally virtual environment into DIRECTORY.
|
||||
(Default: /root/rally if not root).
|
||||
--url Git repository public URL to download Rally from.
|
||||
This is useful when you have only installation script and want
|
||||
to install Rally from custom repository.
|
||||
(Default: https://git.openstack.org/openstack/rally).
|
||||
(Ignored when you are already in git repository).
|
||||
--branch Git branch name, tag (Rally release), commit hash, ref, or other
|
||||
tree-ish to install. (Default: master)
|
||||
Ignored when you are already in git repository.
|
||||
-f, --overwrite Deprecated. Use -r instead.
|
||||
-r, --recreate Remove target directory if it already exist.
|
||||
If neither '-r' nor '-R' is set default behaviour is to ask.
|
||||
-R, --no-recreate Do not remove target directory if it already exist.
|
||||
If neither '-r' nor '-R' is set default behaviour is to ask.
|
||||
-y, --yes Do not ask for confirmation: assume a 'yes' reply
|
||||
to every question.
|
||||
-D, --dbtype TYPE Select the database type. TYPE can be one of
|
||||
'sqlite', 'mysql', 'postgresql'.
|
||||
Default: sqlite
|
||||
--db-user USER Database user to use. Only used when --dbtype
|
||||
is either 'mysql' or 'postgresql'.
|
||||
--db-password PASSWORD Password of the database user. Only used when
|
||||
--dbtype is either 'mysql' or 'postgresql'.
|
||||
--db-host HOST Database host. Only used when --dbtype is
|
||||
either 'mysql' or 'postgresql'
|
||||
--db-name NAME Name of the database. Only used when --dbtype is
|
||||
either 'mysql' or 'postgresql'
|
||||
-p, --python EXE The python interpreter to use. Default: /usr/bin/python.
|
||||
--develop Install Rally with editable source code try. (Default: false)
|
||||
--no-color Disable output coloring.
|
||||
|
||||
|
||||
**Notes:** the script will check if all the software required by Rally
|
||||
is already installed in your system. If this is not the case, it will
|
||||
exit, suggesting you the command to issue **as root** in order to
|
||||
install the dependencies.
|
||||
|
||||
You also have to set up the **Rally database** after the installation is
|
||||
complete:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
rally db recreate
|
||||
|
||||
.. include:: ../../../devstack/README.rst
|
||||
|
||||
Rally & Docker
|
||||
--------------
|
||||
|
||||
First you need to install Docker; Docker supplies `installation
|
||||
instructions for various OSes`_.
|
||||
|
||||
You can either use the official Rally Docker image, or build your own
|
||||
from the Rally source. To do that, change directory to the root directory of
|
||||
the Rally git repository and run:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
docker build -t myrally .
|
||||
|
||||
If you build your own Docker image, substitute ``myrally`` for
|
||||
``xrally/xrally-openstack`` in the commands below.
|
||||
|
||||
The Rally Docker image is configured to store the database in the user's home
|
||||
directory - ``/home/rally/data/rally.sqlite``. For persistence of these data,
|
||||
you may want to keep this directory outside of the container. This may
|
||||
be done via 2 ways:
|
||||
|
||||
* use a docker image. In this case you do not need to initialize the database
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
docker volume create --name rally_volume
|
||||
docker run -v rally_volume:/home/rally/data xrally/xrally-openstack deployment create --name "foo"
|
||||
|
||||
* mount the directory to container. In this case, there is ability to transmit
|
||||
task files inside the container, but you will need to initialize the database
|
||||
by yourself
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo mkdir /var/lib/rally_container
|
||||
sudo chown 65500 /var/lib/rally_container
|
||||
docker run -v /var/lib/rally_container:/home/rally/data xrally/xrally-openstack db create
|
||||
docker run -v /var/lib/rally_container:/home/rally/data xrally/xrally-openstack deployment create --name "foo"
|
||||
|
||||
.. note::
|
||||
|
||||
In order for the volume to be accessible by the Rally user
|
||||
(uid: 65500) inside the container, it must be accessible by UID
|
||||
65500 *outside* the container as well, which is why it is created
|
||||
in ``/var/lib/rally_container``. Creating it in your home directory is only
|
||||
likely to work if your home directory has excessively open
|
||||
permissions (e.g., ``0755``), which is not recommended.
|
||||
|
||||
You can find all task samples, docs and pre created tasks at /home/rally/source
|
||||
In case you have SELinux enabled and Rally fails to create the
|
||||
database, try executing the following commands to put SELinux into
|
||||
Permissive Mode on the host machine
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config
|
||||
setenforce permissive
|
||||
|
||||
Rally currently has no SELinux policy, which is why it must be run in
|
||||
Permissive mode for certain configurations. If you can help create an
|
||||
SELinux policy for Rally, please contribute!
|
||||
|
||||
More about docker: https://www.docker.com/
|
||||
|
||||
.. references:
|
||||
|
||||
.. _installation script: https://raw.githubusercontent.com/openstack/rally/master/install_rally.sh
|
||||
.. _installation instructions for various OSes: https://docs.docker.com/engine/installation/
|
@ -1,175 +0,0 @@
|
||||
:tocdepth: 1
|
||||
|
||||
.. _glossary:
|
||||
|
||||
========
|
||||
Glossary
|
||||
========
|
||||
|
||||
.. warning:: Unfortunately, our glossary is not full, but the Rally
|
||||
team is working on improving it. If you cannot find a definition in
|
||||
which you are interested, feel free to ping us via IRC
|
||||
(#openstack-rally channel at Freenode) or via E-Mail
|
||||
(openstack-dev@lists.openstack.org with tag [Rally]).
|
||||
|
||||
.. contents::
|
||||
:depth: 1
|
||||
:local:
|
||||
|
||||
Common
|
||||
======
|
||||
|
||||
Alembic
|
||||
-------
|
||||
|
||||
A lightweight database migration tool which powers Rally migrations. Read more
|
||||
at `Official Alembic documentation <http://alembic.readthedocs.io/en/latest/>`_
|
||||
|
||||
DB Migrations
|
||||
-------------
|
||||
|
||||
Rally supports database schema and data transformations, which are also
|
||||
known as migrations. This allows you to get your data up-to-date with
|
||||
latest Rally version.
|
||||
|
||||
Rally
|
||||
-----
|
||||
|
||||
A testing tool that automates and unifies multi-node OpenStack deployment
|
||||
and cloud verification. It can be used as a basic tool
|
||||
for an OpenStack CI/CD system that would continuously improve its SLA,
|
||||
performance and stability.
|
||||
|
||||
Rally Config
|
||||
------------
|
||||
|
||||
Rally behavior can be customized by editing its configuration file,
|
||||
*rally.conf*, in `configparser
|
||||
<https://docs.python.org/3.4/library/configparser.html>`_
|
||||
format. While being installed, Rally generates a config with default
|
||||
values from its `sample
|
||||
<https://github.com/openstack/rally/blob/master/etc/rally/rally.conf.sample>`_.
|
||||
When started, Rally searches for its config in
|
||||
"<sys.prefix>/etc/rally/rally.conf", "~/.rally/rally.conf",
|
||||
"/etc/rally/rally.conf"
|
||||
|
||||
Rally DB
|
||||
--------
|
||||
|
||||
Rally uses a relational database as data storage. Several database backends
|
||||
are supported: SQLite (default), PostgreSQL, and MySQL.
|
||||
The database connection can be set via the configuration file option
|
||||
*[database]/connection*.
|
||||
|
||||
Rally Plugin
|
||||
------------
|
||||
|
||||
Most parts of Rally
|
||||
`are pluggable <https://rally.readthedocs.io/en/latest/plugins.html>`_.
|
||||
Scenarios, runners, contexts and even charts for HTML report are plugins.
|
||||
It is easy to create your own plugin and use it. Read more at
|
||||
`plugin reference <https://rally.readthedocs.io/en/latest/plugin/plugin_reference.html>`_.
|
||||
|
||||
Deployment
|
||||
==========
|
||||
|
||||
Deployment
|
||||
----------
|
||||
|
||||
A set of information about target environment (for example: URI and
|
||||
authentication credentials) which is saved in the database. It is used
|
||||
to define the target system for testing each time a task is started.
|
||||
It has a "type" value which changes task behavior for the selected
|
||||
target system; for example type "openstack" will enable OpenStack
|
||||
authentication and services.
|
||||
|
||||
Task
|
||||
====
|
||||
|
||||
Cleanup
|
||||
-------
|
||||
|
||||
This is a specific context which removes all resources on target
|
||||
system that were created by the current task. If some Rally-related
|
||||
resources remain, please `file a bug
|
||||
<https://bugs.launchpad.net/rally>`_ and attach the task file and a
|
||||
list of remaining resources.
|
||||
|
||||
Context
|
||||
-------
|
||||
|
||||
A type of plugin that can run some actions on the target environment
|
||||
before the workloads start and after the last workload finishes. This
|
||||
allows, for example, preparing the environment for workloads (e.g.,
|
||||
create resources and change parameters) and restoring the environment
|
||||
later. Each Context must implement ``setup()`` and ``cleanup()``
|
||||
methods.
|
||||
|
||||
Input task
|
||||
----------
|
||||
|
||||
A file that describes how to run a Rally Task. It can be in JSON or
|
||||
YAML format. The *rally task start* command needs this file to run
|
||||
the task. The input task is pre-processed by the `Jinja2
|
||||
<http://jinja.pocoo.org/>`_ templating engine so it is very easy to
|
||||
create repeated parts or calculate specific values at runtime. It is
|
||||
also possible to pass values via CLI arguments, using the
|
||||
*--task-args* or *--task-args-file* options.
|
||||
|
||||
Runner
|
||||
------
|
||||
|
||||
This is a Rally plugin which decides how to run Workloads. For
|
||||
example, they can be run serially in a single process, or using
|
||||
concurrency.
|
||||
|
||||
Scenario
|
||||
--------
|
||||
|
||||
Synonym for `Workload <#workload>`_
|
||||
|
||||
Service
|
||||
-------
|
||||
|
||||
Abstraction layer that represents target environment API. For
|
||||
example, this can be some OpenStack service. A Service provides API
|
||||
versioning and action timings, simplifies API calls, and reduces code
|
||||
duplication. It can be used in any Rally plugin.
|
||||
|
||||
SLA
|
||||
---
|
||||
|
||||
Service-Level Agreement (Success Criteria).
|
||||
Allows you to determine whether a subtask or workload is successful
|
||||
by setting success criteria rules.
|
||||
|
||||
Subtask
|
||||
-------
|
||||
|
||||
A part of a Task. There can be many subtasks in a single Task.
|
||||
|
||||
Task
|
||||
----
|
||||
|
||||
An entity which includes all the necessary data for a test run, and
|
||||
results of this run.
|
||||
|
||||
Workload
|
||||
--------
|
||||
|
||||
An important part of Task: a plugin which is run by the runner. It is
|
||||
usually run in separate thread. Workloads are grouped into Subtasks.
|
||||
|
||||
Verify
|
||||
======
|
||||
|
||||
Rally can run different subunit-based testing tools against a target
|
||||
environment, for example `tempest
|
||||
<https://docs.openstack.org/tempest/latest/>`_ for OpenStack.
|
||||
|
||||
.. _glossary-verification:
|
||||
|
||||
Verification
|
||||
------------
|
||||
|
||||
A result of running some third-party subunit-based testing tool.
|
@ -1,25 +0,0 @@
|
||||
..
|
||||
Copyright 2015 Mirantis Inc. 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.
|
||||
|
||||
======================
|
||||
Rally project overview
|
||||
======================
|
||||
|
||||
.. toctree::
|
||||
:glob:
|
||||
|
||||
overview
|
||||
glossary
|
||||
user_stories
|
@ -1,179 +0,0 @@
|
||||
..
|
||||
Copyright 2015 Mirantis Inc. 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.
|
||||
|
||||
.. _overview:
|
||||
|
||||
.. contents::
|
||||
:depth: 1
|
||||
:local:
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
**Rally** is a **generic testing tool** that **automates** and **unifies**
|
||||
multi-node OpenStack deployment, verification, testing & profiling.
|
||||
It can be used as a basic tool for an *OpenStack CI/CD system* that would
|
||||
continuously improve its SLA, performance and stability.
|
||||
|
||||
Who Is Using Rally
|
||||
------------------
|
||||
|
||||
Here's a small selection of some of the many companies using Rally:
|
||||
|
||||
.. image:: ../images/Rally_who_is_using.png
|
||||
:align: center
|
||||
|
||||
Use Cases
|
||||
---------
|
||||
|
||||
Let's take a look at 3 major high level Use Cases of Rally:
|
||||
|
||||
.. image:: ../images/Rally-UseCases.png
|
||||
:align: center
|
||||
|
||||
|
||||
Generally, there are a few typical cases where Rally proves to be of great use:
|
||||
|
||||
1. Automate measuring & profiling focused on how new code changes affect
|
||||
the OS performance;
|
||||
|
||||
2. Using Rally profiler to detect scaling & performance issues;
|
||||
|
||||
3. Investigate how different deployments affect the OS performance:
|
||||
|
||||
* Find the set of suitable OpenStack deployment architectures;
|
||||
* Create deployment specifications for different loads (amount of
|
||||
controllers, swift nodes, etc.);
|
||||
|
||||
4. Automate the search for hardware best suited for particular OpenStack
|
||||
cloud;
|
||||
|
||||
5. Automate the production cloud specification generation:
|
||||
|
||||
* Determine terminal loads for basic cloud operations: VM start & stop,
|
||||
Block Device create/destroy & various OpenStack API methods;
|
||||
* Check performance of basic cloud operations in case of different
|
||||
loads.
|
||||
|
||||
|
||||
Real-life examples
|
||||
------------------
|
||||
|
||||
To be substantive, let's investigate a couple of real-life examples of Rally in
|
||||
action.
|
||||
|
||||
|
||||
How does amqp_rpc_single_reply_queue affect performance?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Rally allowed us to reveal a quite an interesting fact about **Nova**. We used
|
||||
*NovaServers.boot_and_delete* scenario to see how the
|
||||
*amqp_rpc_single_reply_queue* option affects VM bootup time (it turns on a kind
|
||||
of fast RPC). Some time ago it was
|
||||
`shown <https://docs.google.com/file/d/0B-droFdkDaVhVzhsN3RKRlFLODQ/edit?pli=1>`_
|
||||
that cloud performance can be boosted by setting it on, so we naturally decided
|
||||
to check this result with Rally. To make this test, we issued requests for
|
||||
booting and deleting VMs for a number of concurrent users ranging from 1 to 30
|
||||
with and without the investigated option. For each group of users, a total
|
||||
number of 200 requests was issued. Averaged time per request is shown below:
|
||||
|
||||
.. image:: ../images/Amqp_rpc_single_reply_queue.png
|
||||
:align: center
|
||||
|
||||
**So Rally has unexpectedly indicated that setting the
|
||||
*amqp_rpc_single_reply_queue* option apparently affects the cloud performance,
|
||||
but in quite an opposite way rather than it was thought before.**
|
||||
|
||||
|
||||
Performance of Nova list command
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Another interesting result comes from the *NovaServers.boot_and_list_server*
|
||||
scenario, which enabled us to launch the following task with Rally:
|
||||
|
||||
* **Task context**: 1 temporary OpenStack user.
|
||||
* **Task scenario**: boot a single VM from this user & list all VMs.
|
||||
* **Task runner**: repeat this procedure 200 times in a continuous way.
|
||||
|
||||
During the execution of this task, the user has more and more VMs on each
|
||||
iteration. Rally has shown that in this case, the performance of the
|
||||
**VM list** command in Nova is degrading much faster than one might expect:
|
||||
|
||||
.. image:: ../images/Rally_VM_list.png
|
||||
:align: center
|
||||
|
||||
|
||||
Complex scenarios
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
In fact, the vast majority of Rally scenarios is expressed as a sequence of
|
||||
**"atomic" actions**. For example, *NovaServers.snapshot* is composed of 6
|
||||
atomic actions:
|
||||
|
||||
1. boot VM
|
||||
2. snapshot VM
|
||||
3. delete VM
|
||||
4. boot VM from snapshot
|
||||
5. delete VM
|
||||
6. delete snapshot
|
||||
|
||||
Rally measures not only the performance of the scenario as a whole,
|
||||
but also that of single atomic actions. As a result, Rally also displays the
|
||||
atomic actions performance data for each scenario iteration in a quite
|
||||
detailed way:
|
||||
|
||||
.. image:: ../images/Rally_snapshot_vm.png
|
||||
:align: center
|
||||
|
||||
|
||||
Architecture
|
||||
------------
|
||||
|
||||
Usually OpenStack projects are implemented *"as-a-Service"*, so Rally provides
|
||||
this approach. In addition, it implements a *CLI-driven* approach that does not
|
||||
require a daemon:
|
||||
|
||||
1. **Rally as-a-Service**: Run rally as a set of daemons that present Web
|
||||
UI *(work in progress)* so 1 RaaS could be used by a whole team.
|
||||
2. **Rally as-an-App**: Rally as a just lightweight and portable CLI app
|
||||
(without any daemons) that makes it simple to use & develop.
|
||||
|
||||
The diagram below shows how this is possible:
|
||||
|
||||
.. image:: ../images/Rally_Architecture.png
|
||||
:align: center
|
||||
|
||||
The actual **Rally core** consists of 3 main components, listed below in the
|
||||
order they go into action:
|
||||
|
||||
1. **Deploy** - store credentials about your deployments, credentials
|
||||
are used by verify and task commands. It has plugable mechanism that
|
||||
allows one to implement basic LCM for testing environment as well.
|
||||
|
||||
2. **Verify** - wraps unittest based functional testing framework to
|
||||
provide complete tool with result storage and reporting.
|
||||
Currently has only plugin implemneted for OpenStack Tempest.
|
||||
|
||||
3. **Task** - framework that allows to write parametrized plugins and
|
||||
combine them in complex test cases using YAML. Framework allows to
|
||||
produce all kinds of tests including functional, concurrency,
|
||||
regression, load, scale, capacity and even chaos testing.
|
||||
|
||||
It should become fairly obvious why Rally core needs to be split to these parts
|
||||
if you take a look at the following diagram that visualizes a rough **algorithm
|
||||
for starting testing clouds at scale**.
|
||||
|
||||
.. image:: ../images/Rally_QA.png
|
||||
:align: center
|
@ -1 +0,0 @@
|
||||
../../user_stories/
|
@ -1,30 +0,0 @@
|
||||
..
|
||||
Copyright 2015 Mirantis Inc. 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.
|
||||
|
||||
.. _user_stories:
|
||||
|
||||
User stories
|
||||
============
|
||||
|
||||
Rally has made it possible to find performance bugs and validate
|
||||
improvements for different OpenStack installations.
|
||||
You can read some stories below:
|
||||
|
||||
|
||||
.. toctree::
|
||||
:glob:
|
||||
:maxdepth: 1
|
||||
|
||||
stories/**
|
@ -1,139 +0,0 @@
|
||||
..
|
||||
Copyright 2016 Mirantis Inc. 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.
|
||||
|
||||
.. _plugins_context_plugin:
|
||||
|
||||
|
||||
Context as a plugin
|
||||
===================
|
||||
|
||||
So what are contexts doing? These plugins will be executed before
|
||||
scenario iteration starts. For example, a context plugin could create
|
||||
resources (e.g., download 10 images) that will be used by the
|
||||
scenarios. All created objects must be put into the *self.context*
|
||||
dict, through which they will be available in the scenarios. Let's
|
||||
create a simple context plugin that adds a flavor to the environment
|
||||
before runner start first iteration and deletes it after runner finishes
|
||||
execution of all iterations.
|
||||
|
||||
Creation
|
||||
^^^^^^^^
|
||||
|
||||
Inherit a class for your plugin from the base *Context* class. Then,
|
||||
implement the Context API: the *setup()* method that creates a flavor and the
|
||||
*cleanup()* method that deletes it.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from rally.task import context
|
||||
from rally.common import logging
|
||||
from rally.plugins.openstack import osclients
|
||||
|
||||
from rally_openstack import consts
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@context.configure(name="create_flavor", order=1000)
|
||||
class CreateFlavorContext(context.Context):
|
||||
"""This sample creates a flavor with specified option."""
|
||||
|
||||
CONFIG_SCHEMA = {
|
||||
"type": "object",
|
||||
"$schema": consts.JSON_SCHEMA,
|
||||
"additionalProperties": False,
|
||||
"properties": {
|
||||
"flavor_name": {
|
||||
"type": "string",
|
||||
},
|
||||
"ram": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"vcpus": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"disk": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def setup(self):
|
||||
"""This method is called before the task starts."""
|
||||
try:
|
||||
# use rally.osclients to get necessary client instance
|
||||
nova = osclients.Clients(self.context["admin"]["credential"]).nova()
|
||||
# and than do what you need with this client
|
||||
self.context["flavor"] = nova.flavors.create(
|
||||
# context settings are stored in self.config
|
||||
name=self.config.get("flavor_name", "rally_test_flavor"),
|
||||
ram=self.config.get("ram", 1),
|
||||
vcpus=self.config.get("vcpus", 1),
|
||||
disk=self.config.get("disk", 1)).to_dict()
|
||||
LOG.debug("Flavor with id '%s'" % self.context["flavor"]["id"])
|
||||
except Exception as e:
|
||||
msg = "Can't create flavor: %s" % e.message
|
||||
if logging.is_debug():
|
||||
LOG.exception(msg)
|
||||
else:
|
||||
LOG.warning(msg)
|
||||
|
||||
def cleanup(self):
|
||||
"""This method is called after the task finishes."""
|
||||
try:
|
||||
nova = osclients.Clients(self.context["admin"]["credential"]).nova()
|
||||
nova.flavors.delete(self.context["flavor"]["id"])
|
||||
LOG.debug("Flavor '%s' deleted" % self.context["flavor"]["id"])
|
||||
except Exception as e:
|
||||
msg = "Can't delete flavor: %s" % e.message
|
||||
if logging.is_debug():
|
||||
LOG.exception(msg)
|
||||
else:
|
||||
LOG.warning(msg)
|
||||
|
||||
|
||||
Usage
|
||||
^^^^^
|
||||
|
||||
The new plugin can be used by specifying it in context section. Like below:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"Dummy.dummy": [
|
||||
{
|
||||
"args": {
|
||||
"sleep": 0.01
|
||||
},
|
||||
"runner": {
|
||||
"type": "constant",
|
||||
"times": 5,
|
||||
"concurrency": 1
|
||||
},
|
||||
"context": {
|
||||
"users": {
|
||||
"tenants": 1,
|
||||
"users_per_tenant": 1
|
||||
},
|
||||
"create_flavor": {
|
||||
"ram": 1024
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -1,402 +0,0 @@
|
||||
..
|
||||
Copyright 2016 Mirantis Inc. 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.
|
||||
|
||||
.. _hook_and_trigger_plugins:
|
||||
|
||||
|
||||
Hooks. Hook trigger plugins
|
||||
===========================
|
||||
|
||||
|
||||
Why Hooks?
|
||||
----------
|
||||
|
||||
All Rally workloads repeat their actions as many times as it is configured by
|
||||
runner. Once run, there is no way to interrupt the runner to evaluate any
|
||||
change or restart event on the stability of the cloud under test.
|
||||
For example we would like to test how configuration change or cloud component
|
||||
restart would affect performance and stability.
|
||||
|
||||
Task hooks were added to fill this gap and allow to use Rally for reliability
|
||||
and high availability testing. Generally, hooks allow to perform any
|
||||
actions on specified iteration or specified time since the workload has been
|
||||
started.
|
||||
|
||||
Also, task html-report provides results of hook execution. They can contain
|
||||
graphical or textual information with timing and statistics.
|
||||
|
||||
|
||||
Hooks & Triggers Overview
|
||||
-------------------------
|
||||
|
||||
|
||||
Architecture
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Rally uses runners to specify how many times the workload should be executed.
|
||||
Hooks do not use runners, instead they rely on trigger plugins to specify when
|
||||
and how many times hook should be called. Therefore hooks are isolated from
|
||||
workload runners and do not affect them because each hook is executed in
|
||||
separate thread.
|
||||
|
||||
|
||||
Sample of usage
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
Hooks can be added to the task configuration. Lets take a look at hook
|
||||
configuration:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"name": "sys_call",
|
||||
"args": "/bin/echo 123",
|
||||
"trigger": {
|
||||
"name": "event",
|
||||
"args": {
|
||||
"unit": "iteration",
|
||||
"at": [5, 50, 200, 1000]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
It specifies hook plugin with name "sys_call". "args" field contains string
|
||||
that will be used by sys_call plugin, but in case of any other hook plugin it
|
||||
can contain any other Python object, that is assumed to be passed to the hook.
|
||||
"trigger" field specifies which trigger plugin should be used to run this hook.
|
||||
"trigger" contains similar fields "name" and "args" which represent trigger
|
||||
plugin name and arguments for trigger plugin. In this example "event" trigger
|
||||
is specified and configured to run the hook at 5th, 50th, 200th and 1000th
|
||||
iterations.
|
||||
|
||||
Here is a full task config that contains previous hook configuration:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"Dummy.dummy": [
|
||||
{
|
||||
"args": {
|
||||
"sleep": 0.01
|
||||
},
|
||||
"runner": {
|
||||
"type": "constant",
|
||||
"times": 1500,
|
||||
"concurrency": 1
|
||||
},
|
||||
"hooks": [
|
||||
{
|
||||
"name": "sys_call",
|
||||
"args": "/bin/echo 123",
|
||||
"trigger": {
|
||||
"name": "event",
|
||||
"args": {
|
||||
"unit": "iteration",
|
||||
"at": [5, 50, 200, 1000]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
.. note::
|
||||
In this example, runner is configured to run workload 1500 times. So there
|
||||
is a limit for iterations and hook will be triggered only if certain
|
||||
iteration is started by runner. In other words, if trigger specifies
|
||||
iteration out of runner iterations scope then such trigger will not be
|
||||
called.
|
||||
|
||||
Task report for this example will contain minimal information about hook
|
||||
execution: duration of each hook call and its status(success of failure).
|
||||
|
||||
Let's take a look at more complicated config that can produce graphical
|
||||
and textual information.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
---
|
||||
Dummy.dummy:
|
||||
-
|
||||
args:
|
||||
sleep: 0.75
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 20
|
||||
concurrency: 2
|
||||
hooks:
|
||||
- name: sys_call
|
||||
description: Run script
|
||||
args: sh rally/rally-jobs/extra/hook_example_script.sh
|
||||
trigger:
|
||||
name: event
|
||||
args:
|
||||
unit: iteration
|
||||
at: [2, 5, 8, 13, 17]
|
||||
- name: sys_call
|
||||
description: Show time
|
||||
args: date +%Y-%m-%dT%H:%M:%S
|
||||
trigger:
|
||||
name: event
|
||||
args:
|
||||
unit: time
|
||||
at: [0, 2, 5, 6, 9]
|
||||
- name: sys_call
|
||||
description: Show system name
|
||||
args: uname -a
|
||||
trigger:
|
||||
name: event
|
||||
args:
|
||||
unit: iteration
|
||||
at: [2, 3, 4, 5, 6, 8, 10, 12, 13, 15, 17, 18]
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
||||
|
||||
|
||||
hook_example_script.sh generates dummy output in JSON format. Grafical
|
||||
information format is the same as for workloads and the same types of
|
||||
charts are supported for the hooks.
|
||||
|
||||
Here is a report that shows aggregated table and chart with hook results:
|
||||
|
||||
.. image:: ../../images/Hook-Aggregated-Report.png
|
||||
|
||||
Here is report that shows lines chart and pie chart for first hook on
|
||||
the second iteration:
|
||||
|
||||
.. image:: ../../images/Hook-Per-Hook-Report.png
|
||||
|
||||
Browse existing Hooks_ and Triggers_.
|
||||
|
||||
|
||||
Writing your own Hook plugin
|
||||
----------------------------
|
||||
|
||||
Problem description
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Hook plugin should implement custom action that can be done one or multiple
|
||||
times during the workload. Examples of such actions might be the following:
|
||||
|
||||
- Destructive action inside cloud (`Fault Injection`_)
|
||||
- Getting information about current state of cloud (load/health)
|
||||
- Upgrading/downgrading a component of cloud
|
||||
- Changing configuration of cloud
|
||||
- etc.
|
||||
|
||||
|
||||
Plugin code
|
||||
^^^^^^^^^^^
|
||||
|
||||
The following example shows simple hook code that performs system call.
|
||||
It is inherited from the base *Hook* class and contains implemented ``run()``
|
||||
method:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import shlex
|
||||
import subprocess
|
||||
|
||||
from rally.task import hook
|
||||
|
||||
from rally_openstack import consts
|
||||
|
||||
@hook.configure(name="simple_sys_call")
|
||||
class SimpleSysCallHook(hook.Hook):
|
||||
"""Performs system call."""
|
||||
|
||||
CONFIG_SCHEMA = {
|
||||
"$schema": consts.JSON_SCHEMA,
|
||||
"type": "string",
|
||||
}
|
||||
|
||||
def run(self):
|
||||
proc = subprocess.Popen(shlex.split(self.config),
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT)
|
||||
proc.wait()
|
||||
if proc.returncode:
|
||||
self.set_error(
|
||||
exception_name="n/a", # no exception class
|
||||
description="Subprocess returned {}".format(proc.returncode),
|
||||
details=proc.stdout.read(),
|
||||
)
|
||||
|
||||
Any exceptions risen during execution of ``run`` method will be caught by Hook
|
||||
base class and saved as a result. Although hook should manually call
|
||||
``Hook.set_error()`` to indicate logical error in case if there is no exception
|
||||
raised.
|
||||
|
||||
Also there is a method for saving charts data: ``Hook.add_output()``.
|
||||
|
||||
|
||||
Plugin Placement
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
There are two folders for hook plugins:
|
||||
|
||||
- `OpenStack Hooks`_
|
||||
- `Common Hooks`_
|
||||
|
||||
|
||||
Sample of task that uses Hook
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"Dummy.dummy": [
|
||||
{
|
||||
"args": {
|
||||
"sleep": 0.01
|
||||
},
|
||||
"runner": {
|
||||
"type": "constant",
|
||||
"times": 10,
|
||||
"concurrency": 1
|
||||
},
|
||||
"hooks": [
|
||||
{
|
||||
"name": "simple_sys_call",
|
||||
"args": "/bin/echo 123",
|
||||
"trigger": {
|
||||
"name": "event",
|
||||
"args": {
|
||||
"unit": "iteration",
|
||||
"at": [3, 6]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
Results of task execution
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Result of previous task example:
|
||||
|
||||
.. image:: ../../images/Hook-Results.png
|
||||
|
||||
|
||||
Writing your own Trigger plugin
|
||||
-------------------------------
|
||||
|
||||
|
||||
Problem description
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Trigger plugin should implement an event processor that decides whether to
|
||||
start hook or not. Rally has two basic triggers that should cover most cases:
|
||||
|
||||
- `Event Trigger`_
|
||||
- `Periodic Trigger`_
|
||||
|
||||
|
||||
Plugin code
|
||||
^^^^^^^^^^^
|
||||
|
||||
This example shows the code of the existing Event trigger:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from rally.task import trigger
|
||||
|
||||
from rally_openstack import consts
|
||||
|
||||
@trigger.configure(name="event")
|
||||
class EventTrigger(trigger.Trigger):
|
||||
"""Triggers hook on specified event and list of values."""
|
||||
|
||||
CONFIG_SCHEMA = {
|
||||
"type": "object",
|
||||
"$schema": consts.JSON_SCHEMA,
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"unit": {"enum": ["time"]},
|
||||
"at": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"uniqueItems": True,
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
}
|
||||
},
|
||||
},
|
||||
"required": ["unit", "at"],
|
||||
"additionalProperties": False,
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"unit": {"enum": ["iteration"]},
|
||||
"at": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"uniqueItems": True,
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
}
|
||||
},
|
||||
},
|
||||
"required": ["unit", "at"],
|
||||
"additionalProperties": False,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
def get_listening_event(self):
|
||||
return self.config["unit"]
|
||||
|
||||
def on_event(self, event_type, value=None):
|
||||
if not (event_type == self.get_listening_event()
|
||||
and value in self.config["at"]):
|
||||
# do nothing
|
||||
return
|
||||
super(EventTrigger, self).on_event(event_type, value)
|
||||
|
||||
|
||||
Trigger plugins must override two methods:
|
||||
|
||||
- ``get_listening_event`` - this method should return currently configured
|
||||
event name. (So far Rally supports only "time" and "iteration")
|
||||
- ``on_event`` - this method is called each time certain events occur.
|
||||
It calls base method when the hook is triggered on specified event.
|
||||
|
||||
|
||||
Plugin Placement
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
All trigger plugins should be placed in `Trigger folder`_.
|
||||
|
||||
|
||||
.. references:
|
||||
|
||||
.. _Hooks: ../plugin_reference.html#task-hooks
|
||||
.. _Triggers: ../plugin_reference.html#task-hook-triggers
|
||||
.. _Fault Injection: ../plugin_reference.html#fault-injection-hook
|
||||
.. _Event Trigger: ../plugin_reference.html#event-hook-trigger
|
||||
.. _Periodic Trigger: ../plugin_reference.html#periodic-hook-trigger
|
||||
.. _Common Hooks: https://github.com/openstack/rally/tree/master/rally/plugins/common/hook
|
||||
.. _OpenStack Hooks: https://github.com/openstack/rally/tree/master/rally/plugins/openstack/hook
|
||||
.. _Trigger folder: https://github.com/openstack/rally/tree/master/rally/plugins/common/trigger
|
@ -1,108 +0,0 @@
|
||||
..
|
||||
Copyright 2016 Mirantis Inc. 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.
|
||||
|
||||
.. _plugins_runner_plugin:
|
||||
|
||||
Scenario runner as a plugin
|
||||
===========================
|
||||
|
||||
Let's create a runner plugin that runs a given scenario a random number of
|
||||
times (chosen at random from a given range).
|
||||
|
||||
Creation
|
||||
^^^^^^^^
|
||||
|
||||
Inherit a class for your plugin from the base *ScenarioRunner* class
|
||||
and implement its API (the *_run_scenario()* method):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import random
|
||||
|
||||
from rally.task import runner
|
||||
|
||||
from rally_openstack import consts
|
||||
|
||||
|
||||
@runner.configure(name="random_times")
|
||||
class RandomTimesScenarioRunner(runner.ScenarioRunner):
|
||||
"""Sample scenario runner plugin.
|
||||
|
||||
Run scenario random number of times (between min_times and max_times)
|
||||
"""
|
||||
|
||||
CONFIG_SCHEMA = {
|
||||
"type": "object",
|
||||
"$schema": consts.JSON_SCHEMA,
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"min_times": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"max_times": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
}
|
||||
},
|
||||
"additionalProperties": True
|
||||
}
|
||||
|
||||
def _run_scenario(self, cls, method_name, context, args):
|
||||
# runners settings are stored in self.config
|
||||
min_times = self.config.get('min_times', 1)
|
||||
max_times = self.config.get('max_times', 1)
|
||||
|
||||
for i in range(random.randrange(min_times, max_times)):
|
||||
run_args = (i, cls, method_name,
|
||||
runner._get_scenario_context(context), args)
|
||||
result = runner._run_scenario_once(run_args)
|
||||
# use self.send_result for result of each iteration
|
||||
self._send_result(result)
|
||||
|
||||
Usage
|
||||
^^^^^
|
||||
|
||||
You can refer to your scenario runner in the input task files in the same way
|
||||
as any other runners. Don't forget to put your runner-specific parameters
|
||||
in the configuration as well (*"min_times"* and *"max_times"* in our example):
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"Dummy.dummy": [
|
||||
{
|
||||
"runner": {
|
||||
"type": "random_times",
|
||||
"min_times": 10,
|
||||
"max_times": 20,
|
||||
},
|
||||
"context": {
|
||||
"users": {
|
||||
"tenants": 1,
|
||||
"users_per_tenant": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Different plugin samples are available
|
||||
`here <https://github.com/openstack/rally/tree/master/samples/plugins>`_.
|
@ -1,91 +0,0 @@
|
||||
..
|
||||
Copyright 2016 Mirantis Inc. 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.
|
||||
|
||||
.. _plugins_scenario_plugin:
|
||||
|
||||
|
||||
Scenario as a plugin
|
||||
====================
|
||||
|
||||
Let's create a simple scenario plugin that list flavors.
|
||||
|
||||
Creation
|
||||
^^^^^^^^
|
||||
|
||||
Inherit a class for your plugin from the base *OpenStackScenario* class and
|
||||
implement a scenario method inside it. In our scenario, we'll first
|
||||
list flavors as an ordinary user, and then repeat the same using admin
|
||||
clients:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from rally.plugins.openstack import scenario
|
||||
from rally.task import atomic
|
||||
from rally.task import validation
|
||||
|
||||
from rally_openstack import consts
|
||||
|
||||
|
||||
@validation.add("required_services", services=[consts.Service.NOVA])
|
||||
@validation.add("required_platform", platform="openstack", users=True)
|
||||
@scenario.configure(name="ScenarioPlugin.list_flavors_useless")
|
||||
class ListFlavors(scenario.OpenStackScenario):
|
||||
"""Sample plugin which lists flavors."""
|
||||
|
||||
@atomic.action_timer("list_flavors")
|
||||
def _list_flavors(self):
|
||||
"""Sample of usage clients - list flavors
|
||||
|
||||
You can use self.context, self.admin_clients and self.clients
|
||||
which are initialized on scenario instance creation"""
|
||||
self.clients("nova").flavors.list()
|
||||
|
||||
@atomic.action_timer("list_flavors_as_admin")
|
||||
def _list_flavors_as_admin(self):
|
||||
"""The same with admin clients"""
|
||||
self.admin_clients("nova").flavors.list()
|
||||
|
||||
def run(self):
|
||||
"""List flavors."""
|
||||
self._list_flavors()
|
||||
self._list_flavors_as_admin()
|
||||
|
||||
|
||||
Usage
|
||||
^^^^^
|
||||
|
||||
You can refer to your plugin scenario in the task input files in the same
|
||||
way as any other scenarios:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"ScenarioPlugin.list_flavors": [
|
||||
{
|
||||
"runner": {
|
||||
"type": "serial",
|
||||
"times": 5,
|
||||
},
|
||||
"context": {
|
||||
"create_flavor": {
|
||||
"ram": 512,
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
This configuration file uses the *"create_flavor"* context which we
|
||||
created in :ref:`plugins_context_plugin`.
|
@ -1,97 +0,0 @@
|
||||
..
|
||||
Copyright 2016 Mirantis Inc. 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.
|
||||
|
||||
.. _plugins_sla_plugin:
|
||||
|
||||
|
||||
SLA as a plugin
|
||||
===============
|
||||
|
||||
Let's create an SLA (success criterion) plugin that checks whether the
|
||||
range of the observed performance measurements does not exceed the
|
||||
allowed maximum value.
|
||||
|
||||
Creation
|
||||
^^^^^^^^
|
||||
|
||||
Inherit a class for your plugin from the base *SLA* class and implement its API
|
||||
(the *add_iteration(iteration)*, the *details()* method):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from rally.task import sla
|
||||
|
||||
@sla.configure(name="max_duration_range")
|
||||
class MaxDurationRange(sla.SLA):
|
||||
"""Maximum allowed duration range in seconds."""
|
||||
|
||||
CONFIG_SCHEMA = {
|
||||
"type": "number",
|
||||
"minimum": 0.0,
|
||||
}
|
||||
|
||||
def __init__(self, criterion_value):
|
||||
super(MaxDurationRange, self).__init__(criterion_value)
|
||||
self._min = 0
|
||||
self._max = 0
|
||||
|
||||
def add_iteration(self, iteration):
|
||||
# Skipping failed iterations (that raised exceptions)
|
||||
if iteration.get("error"):
|
||||
return self.success # This field is defined in base class
|
||||
|
||||
# Updating _min and _max values
|
||||
self._max = max(self._max, iteration["duration"])
|
||||
self._min = min(self._min, iteration["duration"])
|
||||
|
||||
# Updating successfulness based on new max and min values
|
||||
self.success = self._max - self._min <= self.criterion_value
|
||||
return self.success
|
||||
|
||||
def details(self):
|
||||
return ("%s - Maximum allowed duration range: %.2f%% <= %.2f%%"
|
||||
% (self.status(), self._max - self._min, self.criterion_value))
|
||||
|
||||
|
||||
Usage
|
||||
^^^^^
|
||||
|
||||
The new plugin can be used by specifying it in SLA section. Like below:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"Dummy.dummy": [
|
||||
{
|
||||
"args": {
|
||||
"sleep": 0.01
|
||||
},
|
||||
"runner": {
|
||||
"type": "constant",
|
||||
"times": 5,
|
||||
"concurrency": 1
|
||||
},
|
||||
"context": {
|
||||
"users": {
|
||||
"tenants": 1,
|
||||
"users_per_tenant": 1
|
||||
}
|
||||
},
|
||||
"sla": {
|
||||
"max_duration_range": 2.5
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
..
|
||||
Copyright 2015 Mirantis Inc. 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.
|
||||
|
||||
.. _plugins:
|
||||
|
||||
Rally Plugins
|
||||
=============
|
||||
|
||||
Rally has a plugin oriented architecture - in other words Rally team is trying
|
||||
to make all places of code pluggable. Such architecture leads to the big amount
|
||||
of plugins. :ref:`plugin-reference` contains a full list of all official Rally
|
||||
plugins with detailed descriptions.
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
plugin_reference
|
||||
|
||||
How plugins work
|
||||
----------------
|
||||
|
||||
Rally provides an opportunity to create and use a **custom task
|
||||
scenario, runner, SLA, deployment or context** as a **plugin**:
|
||||
|
||||
.. image:: ../images/Rally-Plugins.png
|
||||
:align: center
|
||||
|
||||
Placement
|
||||
---------
|
||||
|
||||
Plugins can be quickly written and used, with no need to contribute
|
||||
them to the actual Rally code. Just place a Python module with your
|
||||
plugin class into the ``/opt/rally/plugins`` or ``~/.rally/plugins``
|
||||
directory (or its subdirectories), and it will be
|
||||
automatically loaded. Additional paths can be specified with the
|
||||
``--plugin-paths`` argument, or with the ``RALLY_PLUGIN_PATHS``
|
||||
environment variable, both of which accept comma-delimited
|
||||
lists. Both ``--plugin-paths`` and ``RALLY_PLUGIN_PATHS`` can list
|
||||
either plugin module files, or directories containing plugins. For
|
||||
instance, both of these are valid:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
rally --plugin-paths /rally/plugins ...
|
||||
rally --plugin-paths /rally/plugins/foo.py,/rally/plugins/bar.py ...
|
||||
|
||||
You can also use a script ``unpack_plugins_samples.sh`` from
|
||||
``samples/plugins`` which will automatically create the
|
||||
``~/.rally/plugins`` directory.
|
||||
|
||||
How to create a plugin
|
||||
----------------------
|
||||
|
||||
To create your own plugin you need to inherit your plugin class from
|
||||
plugin.Plugin class or its subclasses. Also you need to decorate your class
|
||||
with ``rally.task.scenario.configure``
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from rally.task import scenario
|
||||
|
||||
@scenario.configure(name="my_new_plugin_name")
|
||||
class MyNewPlugin(plugin.Plugin):
|
||||
pass
|
||||
|
||||
|
||||
.. toctree::
|
||||
:glob:
|
||||
:maxdepth: 1
|
||||
|
||||
implementation/**
|
@ -1,13 +0,0 @@
|
||||
:tocdepth: 1
|
||||
|
||||
.. _plugin-reference:
|
||||
|
||||
|
||||
Plugins Reference
|
||||
=================
|
||||
|
||||
.. contents::
|
||||
:depth: 2
|
||||
:local:
|
||||
|
||||
.. generate_plugin_reference::
|
@ -1,175 +0,0 @@
|
||||
..
|
||||
Copyright 2015 Mirantis Inc. 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.
|
||||
|
||||
.. _project_info:
|
||||
|
||||
Project Info and Release Notes
|
||||
==============================
|
||||
|
||||
Maintainers
|
||||
-----------
|
||||
|
||||
Project Team Lead (PTL)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
+------------------------------+------------------------------------------------+
|
||||
| Contact | Area of interest |
|
||||
+------------------------------+------------------------------------------------+
|
||||
| | Andrey Kurilin | * Chief Architect |
|
||||
| | andreykurilin (irc) | * Release management |
|
||||
| | andreykurilin (gitter) | * Community management |
|
||||
| | andr.kurilin@gmail.com | * Core team management |
|
||||
| | | * Road Map |
|
||||
+------------------------------+------------------------------------------------+
|
||||
|
||||
| *If you would like to refactor whole Rally or have UX/community/other
|
||||
issues please contact me.*
|
||||
|
||||
|
||||
Project Core maintainers
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
+------------------------------+------------------------------------------------+
|
||||
| Contact | Area of interest |
|
||||
+------------------------------+------------------------------------------------+
|
||||
| | Alexander Maretskiy | * Rally reports |
|
||||
| | amaretskiy (irc) | * Front-end |
|
||||
| | amaretskiy@mirantis.com | |
|
||||
+------------------------------+------------------------------------------------+
|
||||
| | Anton Studenov | * Rally Deployment |
|
||||
| | tohin (irc) | * Task Hooks |
|
||||
| | astudenov@mirantis.com | |
|
||||
+------------------------------+------------------------------------------------+
|
||||
| | Boris Pavlovic | * Founder and ideological leader |
|
||||
| | boris-42 (irc) | * Architect |
|
||||
| | boris@pavlovic.me | * Rally task & plugins |
|
||||
+------------------------------+------------------------------------------------+
|
||||
| | Chen Haibing | * Rally task & plugins |
|
||||
| | chenhb-zte (gitter) | |
|
||||
| | chen.haibing1@zte.com.cn | |
|
||||
+------------------------------+------------------------------------------------+
|
||||
| | Chris St. Pierre | * Rally task & plugins |
|
||||
| | stpierre (irc) | * Bash guru ;) |
|
||||
| | cstpierr@cisco.com | |
|
||||
+------------------------------+------------------------------------------------+
|
||||
| | Hai Shi | * Rally task & plugins |
|
||||
| | shihai1991 (gitter) | |
|
||||
| | shihai1992@gmail.com | |
|
||||
+------------------------------+------------------------------------------------+
|
||||
| | Illia Khudoshyn | * Rally task & plugins |
|
||||
| | ikhudoshyn (irc) | |
|
||||
| | ikhudoshyn@mirantis.com | |
|
||||
+------------------------------+------------------------------------------------+
|
||||
| | Kun Huang | * Rally task & plugins |
|
||||
| | kun_huang (irc) | |
|
||||
| | gareth.huang@huawei.com | |
|
||||
+------------------------------+------------------------------------------------+
|
||||
| | Li Yingjun | * Rally task & plugins |
|
||||
| | liyingjun (irc) | |
|
||||
| | yingjun.li@kylin-cloud.com | |
|
||||
+------------------------------+------------------------------------------------+
|
||||
| | Roman Vasilets | * Rally task & plugins |
|
||||
| | rvasilets (irc) | |
|
||||
| | pomeo92@gmail.com | |
|
||||
+------------------------------+------------------------------------------------+
|
||||
| | Sergey Skripnick | * Rally CI/CD |
|
||||
| | redixin (irc) | * Rally deploy |
|
||||
| | sskripnick@mirantis.com | * Automation of everything |
|
||||
+------------------------------+------------------------------------------------+
|
||||
| | Yaroslav Lobankov | * Rally Verification |
|
||||
| | ylobankov (irc) | |
|
||||
| | ylobankov@mirantis.com | |
|
||||
+------------------------------+------------------------------------------------+
|
||||
|
||||
| *All cores from this list are reviewing all changes that are proposed to Rally.
|
||||
To avoid duplication of efforts, please contact them before starting work on
|
||||
your code.*
|
||||
|
||||
|
||||
Plugin Core reviewers
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
+------------------------------+------------------------------------------------+
|
||||
| Contact | Area of interest |
|
||||
+------------------------------+------------------------------------------------+
|
||||
| | Ivan Kolodyazhny | * Cinder plugins |
|
||||
| | e0ne (irc) | |
|
||||
| | e0ne@e0ne.info | |
|
||||
+------------------------------+------------------------------------------------+
|
||||
| | Nikita Konovalov | * Sahara plugins |
|
||||
| | NikitaKonovalov (irc) | |
|
||||
| | nkonovalov@mirantis.com | |
|
||||
+------------------------------+------------------------------------------------+
|
||||
| | Oleg Bondarev | * Neutron plugins |
|
||||
| | obondarev (irc) | |
|
||||
| | obondarev@mirantis.com | |
|
||||
+------------------------------+------------------------------------------------+
|
||||
| | Sergey Kraynev | * Heat plugins |
|
||||
| | skraynev (irc) | |
|
||||
| | skraynev@mirantis.com | |
|
||||
+------------------------------+------------------------------------------------+
|
||||
| | Spyros Trigazis | * Magnum plugins |
|
||||
| | strigazi (irc) | |
|
||||
| | strigazi@gmail.com | |
|
||||
+------------------------------+------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
| *All cores from this list are responsible for their component plugins.
|
||||
To avoid duplication of efforts, please contact them before starting working
|
||||
on your own plugins.*
|
||||
|
||||
|
||||
Useful links
|
||||
------------
|
||||
- `Source code`_
|
||||
- `Rally roadmap`_
|
||||
- `Project space`_
|
||||
- `Bugs`_
|
||||
- `Patches on review`_
|
||||
- `Meeting logs`_ (server: **irc.freenode.net**, channel:
|
||||
**#openstack-meeting**)
|
||||
- `IRC logs`_ (server: **irc.freenode.net**, channel: **#openstack-rally**)
|
||||
- `Gitter chat`_
|
||||
- `Trello board`_
|
||||
|
||||
|
||||
Where can I discuss and propose changes?
|
||||
----------------------------------------
|
||||
- Our IRC channel: **#openstack-rally** on **irc.freenode.net**;
|
||||
- Weekly Rally team meeting (in IRC): **#openstack-meeting** on
|
||||
**irc.freenode.net**, held on Mondays at 14:00 UTC;
|
||||
- OpenStack mailing list: **openstack-dev@lists.openstack.org** (see
|
||||
`subscription and usage instructions`_);
|
||||
- `Rally team on Launchpad`_: Answers/Bugs/Blueprints.
|
||||
|
||||
.. _release_notes:
|
||||
|
||||
.. include:: release_notes.rst
|
||||
|
||||
.. references:
|
||||
|
||||
.. _Source code: https://github.com/openstack/rally
|
||||
.. _Rally roadmap: https://docs.google.com/a/mirantis.com/spreadsheets/d/16DXpfbqvlzMFaqaXAcJsBzzpowb_XpymaK2aFY2gA2g/edit#gid=0
|
||||
.. _Project space: https://launchpad.net/rally
|
||||
.. _Bugs: https://bugs.launchpad.net/rally
|
||||
.. _Patches on review: https://review.openstack.org/#/q/status:open+project:openstack/rally,n,z
|
||||
.. _Meeting logs: http://eavesdrop.openstack.org/meetings/rally/2016/
|
||||
.. _IRC logs: http://irclog.perlgeek.de/openstack-rally
|
||||
.. _Gitter chat: https://gitter.im/rally-dev/Lobby
|
||||
.. _Trello board: https://trello.com/b/DoD8aeZy/rally
|
||||
.. _subscription and usage instructions: http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
|
||||
.. _Rally team on Launchpad: https://launchpad.net/rally
|
@ -1 +0,0 @@
|
||||
../../release_notes/
|
@ -1,23 +0,0 @@
|
||||
..
|
||||
Copyright 2015 Mirantis Inc. 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.
|
||||
|
||||
Release Notes
|
||||
-------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
release_notes/archive.rst
|
||||
release_notes/latest.rst
|
@ -1,191 +0,0 @@
|
||||
..
|
||||
Copyright 2015 Mirantis Inc. 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.
|
||||
|
||||
.. _gates:
|
||||
|
||||
Rally OpenStack Gates
|
||||
=====================
|
||||
|
||||
Gate jobs
|
||||
---------
|
||||
|
||||
The **OpenStack CI system** uses the so-called **"Gate jobs"** to control
|
||||
merges of patches submitted for review on Gerrit. These **Gate jobs** usually
|
||||
just launch a set of tests -- unit, functional, integration, style -- that
|
||||
check that the proposed patch does not break the software and can be merged
|
||||
into the target branch, thus providing additional guarantees for the stability
|
||||
of the software.
|
||||
|
||||
|
||||
Create a custom Rally Gate job
|
||||
------------------------------
|
||||
|
||||
You can create a **Rally Gate job** for your project to run Rally tasks
|
||||
against the patchsets proposed to be merged into your project.
|
||||
|
||||
To create a rally-gate job, you should create a **rally-jobs/** directory at
|
||||
the root of your project.
|
||||
|
||||
As a rule, this directory contains only **{projectname}.yaml**, but more
|
||||
scenarios and jobs can be added as well. This yaml file is in fact an input
|
||||
Rally task file specifying scenarios that should be run in your gate job.
|
||||
|
||||
To make *{projectname}.yaml* run in gates, you need to add *"rally-jobs"* to
|
||||
the "jobs" section of *projects.yaml* in *openstack-infra/project-config*.
|
||||
|
||||
|
||||
Example: Rally Gate job for Glance
|
||||
----------------------------------
|
||||
|
||||
Let's take a look at an example for the `Glance`_ project:
|
||||
|
||||
Edit *jenkins/jobs/projects.yaml:*
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
- project:
|
||||
name: glance
|
||||
node: 'bare-precise || bare-trusty'
|
||||
tarball-site: tarballs.openstack.org
|
||||
doc-publisher-site: docs.openstack.org
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
||||
- python-icehouse-bitrot-jobs
|
||||
- python-juno-bitrot-jobs
|
||||
- openstack-publish-jobs
|
||||
- translation-jobs
|
||||
**- rally-jobs**
|
||||
|
||||
|
||||
Also add *gate-rally-dsvm-{projectname}* to *zuul/layout.yaml*:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
- name: openstack/glance
|
||||
template:
|
||||
- name: merge-check
|
||||
- name: python26-jobs
|
||||
- name: python-jobs
|
||||
- name: openstack-server-publish-jobs
|
||||
- name: openstack-server-release-jobs
|
||||
- name: periodic-icehouse
|
||||
- name: periodic-juno
|
||||
- name: check-requirements
|
||||
- name: integrated-gate
|
||||
- name: translation-jobs
|
||||
- name: large-ops
|
||||
- name: experimental-tripleo-jobs
|
||||
check:
|
||||
- check-devstack-dsvm-cells
|
||||
**- gate-rally-dsvm-glance**
|
||||
gate:
|
||||
- gate-devstack-dsvm-cells
|
||||
experimental:
|
||||
- gate-grenade-dsvm-forward
|
||||
|
||||
|
||||
To add one more scenario and job, you need to add *{scenarioname}.yaml* file
|
||||
here, and *gate-rally-dsvm-{scenarioname}* to *projects.yaml*.
|
||||
|
||||
For example, you can add *myscenario.yaml* to *rally-jobs* directory in your
|
||||
project and then edit *jenkins/jobs/projects.yaml* in this way:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
- project:
|
||||
name: glance
|
||||
github-org: openstack
|
||||
node: bare-precise
|
||||
tarball-site: tarballs.openstack.org
|
||||
doc-publisher-site: docs.openstack.org
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
||||
- python-havana-bitrot-jobs
|
||||
- openstack-publish-jobs
|
||||
- translation-jobs
|
||||
- rally-jobs
|
||||
**- 'gate-rally-dsvm-{name}':
|
||||
name: myscenario**
|
||||
|
||||
Finally, add *gate-rally-dsvm-myscenario* to *zuul/layout.yaml*:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
- name: openstack/glance
|
||||
template:
|
||||
- name: python-jobs
|
||||
- name: openstack-server-publish-jobs
|
||||
- name: periodic-havana
|
||||
- name: check-requirements
|
||||
- name: integrated-gate
|
||||
check:
|
||||
- check-devstack-dsvm-cells
|
||||
- check-tempest-dsvm-postgres-full
|
||||
- gate-tempest-dsvm-large-ops
|
||||
- gate-tempest-dsvm-neutron-large-ops
|
||||
**- gate-rally-dsvm-myscenario**
|
||||
|
||||
It is also possible to arrange your input task files as templates based on
|
||||
``Jinja2``. Say, you want to set the image names used throughout the
|
||||
*myscenario.yaml* task file as a variable parameter. Then, replace concrete
|
||||
image names in this file with a variable:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
...
|
||||
|
||||
NovaServers.boot_and_delete_server:
|
||||
-
|
||||
args:
|
||||
image:
|
||||
name: {{image_name}}
|
||||
...
|
||||
|
||||
NovaServers.boot_and_list_server:
|
||||
-
|
||||
args:
|
||||
image:
|
||||
name: {{image_name}}
|
||||
...
|
||||
|
||||
and create a file named *myscenario_args.yaml* that will define the parameter
|
||||
values:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
---
|
||||
|
||||
image_name: "^cirros.*-disk$"
|
||||
|
||||
this file will be automatically used by Rally to substitute the variables in
|
||||
*myscenario.yaml*.
|
||||
|
||||
|
||||
Plugins & Extras in Rally Gate jobs
|
||||
-----------------------------------
|
||||
|
||||
Along with scenario configs in yaml, the **rally-jobs** directory can also
|
||||
contain two subdirectories:
|
||||
|
||||
- **plugins**: :ref:`Plugins <plugins>` needed for your gate job;
|
||||
- **extra**: auxiliary files like bash scripts or images.
|
||||
|
||||
Both subdirectories will be copied to *~/.rally/* before the job gets started.
|
||||
|
||||
.. references:
|
||||
|
||||
.. _Glance: https://wiki.openstack.org/wiki/Glance
|
@ -1,30 +0,0 @@
|
||||
..
|
||||
Copyright 2015 Mirantis Inc. 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.
|
||||
|
||||
===========
|
||||
Quick start
|
||||
===========
|
||||
|
||||
This section will guide you through all steps of using Rally - from
|
||||
installation to its advanced usage in different use cases (including running
|
||||
Rally in OpenStack CI system gates to control merges of patches submitted for
|
||||
review on Gerrit code review system).
|
||||
|
||||
.. toctree::
|
||||
:glob:
|
||||
:maxdepth: 2
|
||||
|
||||
tutorial
|
||||
gates
|
@ -1,40 +0,0 @@
|
||||
..
|
||||
Copyright 2015 Mirantis Inc. 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.
|
||||
|
||||
.. _tutorial:
|
||||
|
||||
Rally step-by-step
|
||||
==================
|
||||
|
||||
In the following tutorial, we will guide you step-by-step through different use
|
||||
cases that might occur in Rally, starting with the easy ones and moving towards
|
||||
more complicated cases.
|
||||
|
||||
|
||||
.. toctree::
|
||||
:glob:
|
||||
:maxdepth: 1
|
||||
|
||||
tutorial/step_0_installation
|
||||
tutorial/step_1_setting_up_env_and_running_benchmark_from_samples
|
||||
tutorial/step_2_input_task_format
|
||||
tutorial/step_3_benchmarking_with_existing_users
|
||||
tutorial/step_4_adding_success_criteria_for_benchmarks
|
||||
tutorial/step_5_task_templates
|
||||
tutorial/step_6_aborting_load_generation_on_sla_failure
|
||||
tutorial/step_7_working_with_multple_openstack_clouds
|
||||
tutorial/step_8_discovering_more_plugins
|
||||
tutorial/step_9_verifying_cloud_via_tempest_verifier
|
||||
tutorial/step_10_profiling_openstack_internals
|
@ -1,42 +0,0 @@
|
||||
..
|
||||
Copyright 2015 Mirantis Inc. 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.
|
||||
|
||||
.. _tutorial_step_0_installation:
|
||||
|
||||
Step 0. Installation
|
||||
====================
|
||||
|
||||
The easiest way to install Rally is by running its `installation script`_:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
wget -q -O- https://raw.githubusercontent.com/openstack/rally/master/install_rally.sh | bash
|
||||
# or using curl:
|
||||
curl https://raw.githubusercontent.com/openstack/rally/master/install_rally.sh | bash
|
||||
|
||||
If you execute the script as regular user, Rally will create a new
|
||||
virtual environment in ``~/rally/`` and install in it Rally, and will
|
||||
use `sqlite` as database backend. If you execute the script as root,
|
||||
Rally will be installed system wide. For more installation options,
|
||||
please refer to the :ref:`installation <install>` page.
|
||||
|
||||
**Note:** Rally requires Python version 2.7 or 3.4.
|
||||
|
||||
Now that you have Rally installed, you are ready to start
|
||||
:ref:`testing OpenStack with Rally <tutorial_step_1_setting_up_env_and_running_benchmark_from_samples>`!
|
||||
|
||||
.. references:
|
||||
|
||||
.. _installation script: https://raw.githubusercontent.com/openstack/rally/master/install_rally.sh
|