diff --git a/doc/source/deploy/gmr.rst b/doc/source/deploy/gmr.rst new file mode 100644 index 000000000..31ea4f582 --- /dev/null +++ b/doc/source/deploy/gmr.rst @@ -0,0 +1,52 @@ +.. + Except where otherwise noted, this document is licensed under Creative + Commons Attribution 3.0 License. You can view the license at: + + https://creativecommons.org/licenses/by/3.0/ + +.. _watcher_gmr: + +======================= +Guru Meditation Reports +======================= + +Watcher contains a mechanism whereby developers and system administrators can +generate a report about the state of a running Watcher service. This report +is called a *Guru Meditation Report* (*GMR* for short). + +Generating a GMR +================ + +A *GMR* can be generated by sending the *USR2* signal to any Watcher process +with support (see below). The *GMR* will then be outputted as standard error +for that particular process. + +For example, suppose that ``watcher-api`` has process id ``8675``, and was run +with ``2>/var/log/watcher/watcher-api-err.log``. Then, ``kill -USR2 8675`` +will trigger the Guru Meditation report to be printed to +``/var/log/watcher/watcher-api-err.log``. + +Structure of a GMR +================== + +The *GMR* is designed to be extensible; any particular service may add its +own sections. However, the base *GMR* consists of several sections: + +Package + Shows information about the package to which this process belongs, including + version informations. + +Threads + Shows stack traces and thread ids for each of the threads within this + process. + +Green Threads + Shows stack traces for each of the green threads within this process (green + threads don't have thread ids). + +Configuration + Lists all the configuration options currently accessible via the CONF object + for the current process. + +Plugins + Lists all the plugins currently accessible by the Watcher service. diff --git a/doc/source/dev/plugin/action-plugin.rst b/doc/source/dev/plugin/action-plugin.rst index 6c6718552..dfec436f9 100644 --- a/doc/source/dev/plugin/action-plugin.rst +++ b/doc/source/dev/plugin/action-plugin.rst @@ -55,7 +55,7 @@ Here is an example showing how you can write a plugin called ``DummyAction``: from watcher.applier.actions import base - class DummyAction(baseBaseAction): + class DummyAction(base.BaseAction): @property def schema(self): @@ -90,11 +90,53 @@ Input validation As you can see in the previous example, we are using `Voluptuous`_ to validate the input parameters of an action. So if you want to learn more about how to -work with `Voluptuous`_, you can have a look at their `documentation`_ here: +work with `Voluptuous`_, you can have a look at their `documentation`_: .. _Voluptuous: https://github.com/alecthomas/voluptuous .. _documentation: https://github.com/alecthomas/voluptuous/blob/master/README.md + +Define configuration parameters +=============================== + +At this point, you have a fully functional action. However, in more complex +implementation, you may want to define some configuration options so one can +tune the action to its needs. To do so, you can implement the +:py:meth:`~.Loadable.get_config_opts` class method as followed: + +.. code-block:: python + + from oslo_config import cfg + + class DummyAction(base.BaseAction): + + # [...] + + def execute(self): + assert self.config.test_opt == 0 + + def get_config_opts(self): + return [ + cfg.StrOpt('test_opt', help="Demo Option.", default=0), + # Some more options ... + ] + +The configuration options defined within this class method will be included +within the global ``watcher.conf`` configuration file under a section named by +convention: ``{namespace}.{plugin_name}``. In our case, the ``watcher.conf`` +configuration would have to be modified as followed: + +.. code-block:: ini + + [watcher_actions.dummy] + # Option used for testing. + test_opt = test_value + +Then, the configuration options you define within this method will then be +injected in each instantiated object via the ``config`` parameter of the +:py:meth:`~.BaseAction.__init__` method. + + Abstract Plugin Class ===================== @@ -103,6 +145,7 @@ should implement: .. autoclass:: watcher.applier.actions.base.BaseAction :members: + :special-members: __init__ :noindex: .. py:attribute:: schema diff --git a/doc/source/dev/plugin/planner-plugin.rst b/doc/source/dev/plugin/planner-plugin.rst index dee1cddb8..69e31ca4e 100644 --- a/doc/source/dev/plugin/planner-plugin.rst +++ b/doc/source/dev/plugin/planner-plugin.rst @@ -69,6 +69,49 @@ examples, have a look at the implementation of planners already provided by Watcher like :py:class:`~.DefaultPlanner`. A list with all available planner plugins can be found :ref:`here `. + +Define configuration parameters +=============================== + +At this point, you have a fully functional planner. However, in more complex +implementation, you may want to define some configuration options so one can +tune the planner to its needs. To do so, you can implement the +:py:meth:`~.Loadable.get_config_opts` class method as followed: + +.. code-block:: python + + from oslo_config import cfg + + class DummyPlanner(base.BasePlanner): + + # [...] + + def schedule(self, context, audit_uuid, solution): + assert self.config.test_opt == 0 + # [...] + + def get_config_opts(self): + return [ + cfg.StrOpt('test_opt', help="Demo Option.", default=0), + # Some more options ... + ] + +The configuration options defined within this class method will be included +within the global ``watcher.conf`` configuration file under a section named by +convention: ``{namespace}.{plugin_name}``. In our case, the ``watcher.conf`` +configuration would have to be modified as followed: + +.. code-block:: ini + + [watcher_planners.dummy] + # Option used for testing. + test_opt = test_value + +Then, the configuration options you define within this method will then be +injected in each instantiated object via the ``config`` parameter of the +:py:meth:`~.BasePlanner.__init__` method. + + Abstract Plugin Class ===================== @@ -77,6 +120,7 @@ should implement: .. autoclass:: watcher.decision_engine.planner.base.BasePlanner :members: + :special-members: __init__ :noindex: diff --git a/doc/source/dev/plugin/strategy-plugin.rst b/doc/source/dev/plugin/strategy-plugin.rst index 6598bab42..47ee1c107 100644 --- a/doc/source/dev/plugin/strategy-plugin.rst +++ b/doc/source/dev/plugin/strategy-plugin.rst @@ -163,8 +163,8 @@ modify your ``NewStrategy`` plugin so it now achieves the latter: class NewStrategy(NewGoalBaseStrategy): - def __init__(self, osc=None): - super(NewStrategy, self).__init__(osc) + def __init__(self, config, osc=None): + super(NewStrategy, self).__init__(config, osc) def execute(self, original_model): self.solution.add_action(action_type="nop", @@ -185,6 +185,49 @@ modify your ``NewStrategy`` plugin so it now achieves the latter: return "New strategy" +Define configuration parameters +=============================== + +At this point, you have a fully functional strategy. However, in more complex +implementation, you may want to define some configuration options so one can +tune the strategy to its needs. To do so, you can implement the +:py:meth:`~.Loadable.get_config_opts` class method as followed: + +.. code-block:: python + + from oslo_config import cfg + + class NewStrategy(NewGoalBaseStrategy): + + # [...] + + def execute(self, original_model): + assert self.config.test_opt == 0 + # [...] + + def get_config_opts(self): + return [ + cfg.StrOpt('test_opt', help="Demo Option.", default=0), + # Some more options ... + ] + + +The configuration options defined within this class method will be included +within the global ``watcher.conf`` configuration file under a section named by +convention: ``{namespace}.{plugin_name}``. In our case, the ``watcher.conf`` +configuration would have to be modified as followed: + +.. code-block:: ini + + [watcher_strategies.new_strategy] + # Option used for testing. + test_opt = test_value + +Then, the configuration options you define within this method will then be +injected in each instantiated object via the ``config`` parameter of the +:py:meth:`~.BaseStrategy.__init__` method. + + Abstract Plugin Class ===================== @@ -192,6 +235,7 @@ Here below is the abstract :py:class:`~.BaseStrategy` class: .. autoclass:: watcher.decision_engine.strategy.strategies.base.BaseStrategy :members: + :special-members: __init__ :noindex: .. _strategy_plugin_add_entrypoint: diff --git a/doc/source/dev/plugins.rst b/doc/source/dev/plugins.rst index 7b7b1fe65..7a320b602 100644 --- a/doc/source/dev/plugins.rst +++ b/doc/source/dev/plugins.rst @@ -9,6 +9,10 @@ Available Plugins ================= +In this section we present all the plugins that are shipped along with Watcher. +If you want to know which plugins your Watcher services have access to, you can +use the :ref:`Guru Meditation Reports ` to display them. + .. _watcher_strategies: Strategies diff --git a/doc/source/index.rst b/doc/source/index.rst index ffa549103..b305de524 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -90,6 +90,7 @@ Introduction deploy/installation deploy/user-guide + deploy/gmr Watcher Manual Pages ====================