From 3de2d368c0cb30f2068ccff51b93671e99f96e7f Mon Sep 17 00:00:00 2001 From: David TARDIVEL Date: Wed, 5 Oct 2016 17:05:39 +0200 Subject: [PATCH] Add strategy template doc Developer should provide a detailled documentation about his strategy algorithm to make it even easier to use by a Watcher end user. I propose in this changeset a template for strategy documentation. you will find also a example with basic consolidation strategy. Change-Id: I66da1a33b87a94b508dd23ac7dce4cae6f4e068b --- doc/ext/term.py | 73 +++++++++++- doc/source/conf.py | 2 + doc/source/index.rst | 1 + .../strategies/basic-server-consolidation.rst | 96 +++++++++++++++ doc/source/strategies/strategies.rst | 8 ++ doc/source/strategies/strategy-template.rst | 109 ++++++++++++++++++ .../decision_engine/goal/efficacy/specs.py | 4 +- .../decision_engine/model/collector/nova.py | 12 +- .../strategies/basic_consolidation.py | 31 ++--- 9 files changed, 302 insertions(+), 34 deletions(-) create mode 100644 doc/source/strategies/basic-server-consolidation.rst create mode 100644 doc/source/strategies/strategies.rst create mode 100644 doc/source/strategies/strategy-template.rst diff --git a/doc/ext/term.py b/doc/ext/term.py index ceb88af01..8679334ba 100644 --- a/doc/ext/term.py +++ b/doc/ext/term.py @@ -85,7 +85,12 @@ class WatcherTerm(BaseWatcherDirective): cls_path = self.arguments[0] try: - cls = importlib.import_module(cls_path) + try: + cls = importlib.import_module(cls_path) + except ImportError: + module_name, cls_name = cls_path.rsplit('.', 1) + mod = importlib.import_module(module_name) + cls = getattr(mod, cls_name) except Exception as exc: raise self.error(exc) @@ -97,6 +102,72 @@ class WatcherTerm(BaseWatcherDirective): return node.children +class WatcherFunc(BaseWatcherDirective): + """Directive to import a value returned by a func into the Watcher doc + + **How to use it** + + # inside your .py file + class Bar(object): + + def foo(object): + return foo_string + + + # Inside your .rst file + .. watcher-func:: import.path.to.your.Bar.foo node_classname + + node_classname is decumented here: + http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html + + This directive will then import the value and then interpret it. + """ + + # You need to put an import path as an argument for this directive to work + # required_arguments = 1 + # optional_arguments = 1 + + option_spec = {'format': rst.directives.unchanged} + has_content = True + + def run(self): + if not self.content: + error = self.state_machine.reporter.error( + 'The "%s" directive is empty; content required.' % self.name, + nodes.literal_block(self.block_text, self.block_text), + line=self.lineno) + return [error] + + func_path = self.content[0] + try: + cls_path, func_name = func_path.rsplit('.', 1) + module_name, cls_name = cls_path.rsplit('.', 1) + mod = importlib.import_module(module_name) + cls = getattr(mod, cls_name) + except Exception as exc: + raise self.error(exc) + + cls_obj = cls() + func = getattr(cls_obj, func_name) + textblock = func() + if not isinstance(textblock, str): + textblock = str(textblock) + + self.add_textblock(textblock) + + try: + node_class = getattr(nodes, + self.options.get('format', 'paragraph')) + except Exception as exc: + raise self.error(exc) + + node = node_class() + node.document = self.state.document + self.state.nested_parse(self.result, 0, node) + return [node] + + def setup(app): app.add_directive('watcher-term', WatcherTerm) + app.add_directive('watcher-func', WatcherFunc) return {'version': version_info.version_string()} diff --git a/doc/source/conf.py b/doc/source/conf.py index 91ba606cc..f08e445fa 100755 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -78,6 +78,8 @@ exclude_patterns = [ # them when scanning for input files. 'man/footer.rst', 'man/general-options.rst', + 'strategies/strategy-template.rst', + 'image_src/plantuml/README.rst', ] # If true, '()' will be appended to :func: etc. cross-reference text. diff --git a/doc/source/index.rst b/doc/source/index.rst index 8e01e688f..8b665fac3 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -96,6 +96,7 @@ Introduction deploy/user-guide deploy/policy deploy/gmr + strategies/strategies Watcher Manual Pages ==================== diff --git a/doc/source/strategies/basic-server-consolidation.rst b/doc/source/strategies/basic-server-consolidation.rst new file mode 100644 index 000000000..87a1457bd --- /dev/null +++ b/doc/source/strategies/basic-server-consolidation.rst @@ -0,0 +1,96 @@ +================================== +Basic Offline Server Consolidation +================================== + +Synopsis +-------- + +**display name**: ``basic`` + +**goal**: ``server_consolidation`` + + .. watcher-term:: watcher.decision_engine.strategy.strategies.basic_consolidation + +Requirements +------------ + +Metrics +******* + +The *basic* strategy requires the following metrics: + +============================ ============ ======= ======= +metric service name plugins comment +============================ ============ ======= ======= +``compute.node.cpu.percent`` ceilometer_ none +``cpu_util`` ceilometer_ none +============================ ============ ======= ======= + +.. _ceilometer: http://docs.openstack.org/admin-guide/telemetry-measurements.html#openstack-compute + +Cluster data model +****************** + +Default Watcher's Compute cluster data model: + + .. watcher-term:: watcher.decision_engine.model.collector.nova.NovaClusterDataModelCollector + +Actions +******* + +Default Watcher's actions: + + + .. list-table:: + :widths: 30 30 + :header-rows: 1 + + * - action + - description + * - ``migration`` + - .. watcher-term:: watcher.applier.actions.migration.Migrate + * - ``change_nova_service_state`` + - .. watcher-term:: watcher.applier.actions.change_nova_service_state.ChangeNovaServiceState + +Planner +******* + +Default Watcher's planner: + + .. watcher-term:: watcher.decision_engine.planner.default.DefaultPlanner + +Configuration +------------- + +Strategy parameter is: + +====================== ====== ============= =================================== +parameter type default Value description +====================== ====== ============= =================================== +``migration_attempts`` Number 0 Maximum number of combinations to + be tried by the strategy while + searching for potential candidates. + To remove the limit, set it to 0 +====================== ====== ============= =================================== + +Efficacy Indicator +------------------ + +.. watcher-func:: + :format: literal_block + + watcher.decision_engine.goal.efficacy.specs.ServerConsolidation.get_global_efficacy_indicator + +How to use it ? +--------------- + +.. code-block:: shell + + $ openstack optimize audittemplate create \ + at1 server_consolidation --strategy basic + + $ openstack optimize audit create -a at1 -p migration_attempts=4 + +External Links +-------------- +None. diff --git a/doc/source/strategies/strategies.rst b/doc/source/strategies/strategies.rst new file mode 100644 index 000000000..9af2667fa --- /dev/null +++ b/doc/source/strategies/strategies.rst @@ -0,0 +1,8 @@ +Strategies +========== + +.. toctree:: + :glob: + :maxdepth: 1 + + ./* diff --git a/doc/source/strategies/strategy-template.rst b/doc/source/strategies/strategy-template.rst new file mode 100644 index 000000000..c981a5dcf --- /dev/null +++ b/doc/source/strategies/strategy-template.rst @@ -0,0 +1,109 @@ +============= +Strategy name +============= + +Synopsis +-------- + +**display name**: + +**goal**: + +Add here a complete description of your strategy + +Requirements +------------ + +Metrics +******* + +Write here the list of metrics required by your strategy algorithm (in the form + of a table). If these metrics requires specific Telemetry plugin or other + additional software, please explain here how to deploy them (and add link to + dedicated installation guide). + +Example: + +======================= ============ ======= ======= +metric service name plugins comment +======================= ============ ======= ======= +compute.node.* ceilometer_ none one point every 60s +vm.cpu.utilization_perc monasca_ none +power ceilometer_ kwapi_ one point every 60s +======================= ============ ======= ======= + + +.. _ceilometer: http://docs.openstack.org/admin-guide/telemetry-measurements.html#openstack-compute +.. _monasca: https://github.com/openstack/monasca-agent/blob/master/docs/Libvirt.md +.. _kwapi: https://kwapi.readthedocs.io/en/latest/index.html + + +Cluster data model +****************** + +Default Watcher's cluster data model. + +or + +If your strategy implementation requires a new cluster data model, please + describe it in this section, with a link to model plugin's installation guide. + +Actions +******* + +Default Watcher's actions. + +or + +If your strategy implementation requires new actions, add the list of Action + plugins here (in the form of a table) with a link to the plugin's installation + procedure. + +======== ================= +action description +======== ================= +action1_ This action1 ... +action2_ This action2 ... +======== ================= + +.. _action1 : https://github.com/myrepo/watcher/plugins/action1 +.. _action2 : https://github.com/myrepo/watcher/plugins/action2 + +Planner +******* + +Default Watcher's planner. + +or + +If your strategy requires also a new planner to schedule built actions in time, + please describe it in this section, with a link to planner plugin's + installation guide. + +Configuration +------------- + +If your strategy use configurable parameters, explain here how to tune them. + + +Efficacy Indicator +------------------ + +Add here the Efficacy indicator computed by your strategy. + +How to use it ? +--------------- + +.. code-block:: shell + + $ Write the command line to create an audit with your strategy. + +External Links +-------------- + +If you have written papers, blog articles .... about your strategy into Watcher, + or if your strategy is based from external publication(s), please add HTTP + links and references in this section. + +- `link1 `_ +- `link2 `_ diff --git a/watcher/decision_engine/goal/efficacy/specs.py b/watcher/decision_engine/goal/efficacy/specs.py index 8cf0e1f01..818099c9b 100644 --- a/watcher/decision_engine/goal/efficacy/specs.py +++ b/watcher/decision_engine/goal/efficacy/specs.py @@ -37,9 +37,9 @@ class ServerConsolidation(base.EfficacySpecification): indicators.InstanceMigrationsCount(), ] - def get_global_efficacy_indicator(self, indicators_map): + def get_global_efficacy_indicator(self, indicators_map=None): value = 0 - if indicators_map.instance_migrations_count > 0: + if indicators_map and indicators_map.instance_migrations_count > 0: value = (float(indicators_map.released_compute_nodes_count) / float(indicators_map.instance_migrations_count)) * 100 diff --git a/watcher/decision_engine/model/collector/nova.py b/watcher/decision_engine/model/collector/nova.py index a3fa81c81..4fefee7f1 100644 --- a/watcher/decision_engine/model/collector/nova.py +++ b/watcher/decision_engine/model/collector/nova.py @@ -28,16 +28,10 @@ LOG = log.getLogger(__name__) class NovaClusterDataModelCollector(base.BaseClusterDataModelCollector): - """nova + """Nova cluster data model collector - *Description* - - This Nova cluster data model collector creates an in-memory representation - of the resources exposed by the compute service. - - *Spec URL* - - + The Nova cluster data model collector creates an in-memory + representation of the resources exposed by the compute service. """ def __init__(self, config, osc=None): diff --git a/watcher/decision_engine/strategy/strategies/basic_consolidation.py b/watcher/decision_engine/strategy/strategies/basic_consolidation.py index bfb23f9ea..58b0d9884 100644 --- a/watcher/decision_engine/strategy/strategies/basic_consolidation.py +++ b/watcher/decision_engine/strategy/strategies/basic_consolidation.py @@ -25,6 +25,14 @@ it becomes necessary to migrate VMs among servers to lower the costs. However, migration of VMs introduces runtime overheads and consumes extra energy, thus a good server consolidation strategy should carefully plan for migration in order to both minimize energy consumption and comply to the various SLAs. + +This algorithm not only minimizes the overall number of used servers, but also +minimizes the number of migrations. + +It has been developed only for tests. You must have at least 2 physical compute +nodes to run it, so you can easilly run it on DevStack. It assumes that live +migration is possible on your OpenStack cluster. + """ from oslo_log import log @@ -39,28 +47,7 @@ LOG = log.getLogger(__name__) class BasicConsolidation(base.ServerConsolidationBaseStrategy): - """Basic offline consolidation using live migration - - *Description* - - This is server consolidation algorithm which not only minimizes the overall - number of used servers, but also minimizes the number of migrations. - - *Requirements* - - * You must have at least 2 physical compute nodes to run this strategy. - - *Limitations* - - - It has been developed only for tests. - - It assumes that the virtual machine and the compute node are on the same - private network. - - It assumes that live migrations are possible. - - *Spec URL* - - - """ + """Basic offline consolidation using live migration""" HOST_CPU_USAGE_METRIC_NAME = 'compute.node.cpu.percent' INSTANCE_CPU_USAGE_METRIC_NAME = 'cpu_util'