Merge "[docs] Remove outdated docs"

This commit is contained in:
Zuul 2018-09-22 15:17:06 +00:00 committed by Gerrit Code Review
commit cb28d65439
147 changed files with 0 additions and 13396 deletions

View File

@ -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

View File

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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")

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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"

View File

@ -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)

View File

@ -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.

View File

@ -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."

View File

@ -1,3 +0,0 @@
.body img {
max-width: 100%;
}

View File

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

View File

@ -1,2 +0,0 @@
[theme]
inherit = openstack

View File

@ -1,11 +0,0 @@
.. _cli-reference:
Command Line Interface
======================
.. contents::
:depth: 1
:local:
.. make_cli_reference::

View File

@ -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"

View File

@ -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/

View File

@ -1 +0,0 @@
../feature_request/

View File

@ -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/*

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

View File

@ -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

View File

@ -1 +0,0 @@
../../../rally/common/db/sqlalchemy/migrations/README.rst

View File

@ -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

View File

@ -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/

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -1 +0,0 @@
../../user_stories/

View File

@ -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/**

View File

@ -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
}
}
}
]
}

View File

@ -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

View File

@ -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>`_.

View File

@ -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`.

View File

@ -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
}
}
]
}

View File

@ -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/**

View File

@ -1,13 +0,0 @@
:tocdepth: 1
.. _plugin-reference:
Plugins Reference
=================
.. contents::
:depth: 2
:local:
.. generate_plugin_reference::

View File

@ -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

View File

@ -1 +0,0 @@
../../release_notes/

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

Some files were not shown because too many files have changed in this diff Show More