Watcher Planner Selector
This component is responsible for selecting an appropriate Planner based on config options passed by user for distinct Strategy. Change-Id: I8dd84cef4b9eb25a6cdf448d55a2dd8da3f10f9c Implements: bp watcher-planner-selector
This commit is contained in:
parent
d939277b9f
commit
bff4227aed
218
specs/rocky/approved/watcher-planner-selector.rst
Normal file
218
specs/rocky/approved/watcher-planner-selector.rst
Normal file
@ -0,0 +1,218 @@
|
||||
..
|
||||
This work is licensed under a Creative Commons Attribution 3.0 Unported
|
||||
License.
|
||||
|
||||
http://creativecommons.org/licenses/by/3.0/legalcode
|
||||
|
||||
========================
|
||||
Watcher Planner Selector
|
||||
========================
|
||||
|
||||
https://blueprints.launchpad.net/watcher/+spec/watcher-planner-selector
|
||||
|
||||
`Watcher Planner`_ takes the set of `Actions`_ generated by a `Strategy`_ and
|
||||
builds the design of a workflow which defines how-to schedule in time those
|
||||
different Actions and for each Action what are the prerequisite conditions.
|
||||
It is only possible to choose only one (default) `Planner`_ for all strategies
|
||||
now.
|
||||
|
||||
Custom Planners could be added to Watcher, thereby users can adapt Watcher
|
||||
workflow to their needs. As one of the ways for customization, the option
|
||||
could be added to set concrete Planner for specific Strategy that takes
|
||||
features of users' workflow into account.
|
||||
|
||||
|
||||
Problem description
|
||||
===================
|
||||
|
||||
Currently there is no opportunity to set unique Planner to specific Strategy.
|
||||
User can set default Planner in config file that would be used alongside every
|
||||
Audit.
|
||||
|
||||
If using different Planner is the case, user should change default
|
||||
value to desired one. By doing this we restrict ourselves to use this new
|
||||
Planner with all of the Strategies, what is not desired because some of
|
||||
`Solutions`_ generated by Strategies could be not compatible with the schedule
|
||||
made by this Planner.
|
||||
|
||||
Use Cases
|
||||
----------
|
||||
|
||||
* As an Strategy developer, I want to choose what Planner would be applied to the
|
||||
Solution generated by my Strategy.
|
||||
|
||||
* As an Strategy developer, I expect that if I provide no Planner to my Strategy, it
|
||||
will use default Planner that is set in base Strategy..
|
||||
|
||||
|
||||
Proposed change
|
||||
===============
|
||||
|
||||
We propose to add property to base Strategy class, say 'planner', and set
|
||||
default value to this option in concrete Strategies where appropriate (for
|
||||
example, 'workload_stabilization' Planner as default for Strategy with the
|
||||
same name).
|
||||
|
||||
Planner should be load in AuditHandler. Currently it's done with the help of
|
||||
PlannerManager, that loads sole planner for every Strategy which set by
|
||||
CONF.watcher_planner.planner value. Definitely, PlannerManager do only
|
||||
loading job, so it's better to load Planner without this intermediate layer.
|
||||
Thus we propose to exchange AuditHandler._planner_manager with
|
||||
DefaultPlannerLoader. As a result, PlannerManager could be removed from
|
||||
Watcher.
|
||||
|
||||
Therefore, AuditHandler now should pass desired Planner name to Loader.
|
||||
We propose to get this name from property of the Strategy used in current
|
||||
Audit. In this case we ought to get Strategy object associated with current
|
||||
Audit.
|
||||
|
||||
For this propose, we need to be able to get Strategy prior to
|
||||
AuditHandler._planner_loader.load() method call. It could be be done with the
|
||||
help of StrategyContext class that loads Strategy based on names of Goal and
|
||||
Audit. The problem is that this loading is done during do_execute_strategy()
|
||||
what's a bad design. We propose to move *selecting* of strategy to distinct
|
||||
method, say 'select_strategy':
|
||||
|
||||
::
|
||||
|
||||
def select_strategy(audit, request_context):
|
||||
osc = clients.OpenStackClients()
|
||||
goal = objects.Goal.get_by_id(request_context, audit.goal_id)
|
||||
|
||||
strategy_name = None
|
||||
if audit.strategy_id:
|
||||
strategy = objects.Strategy.get_by_id(
|
||||
request_context, audit.strategy_id)
|
||||
strategy_name = strategy.name
|
||||
|
||||
strategy_selector = default.DefaultStrategySelector(
|
||||
goal_name=goal.name,
|
||||
strategy_name=strategy_name,
|
||||
osc=osc)
|
||||
return strategy_selector.select()
|
||||
|
||||
Now we could call this method not only in do_execute_strategy() to pick
|
||||
strategy only for execution, but also call it in AuditHandler.
|
||||
|
||||
Another benefit to do it in this manner is that if Audit was created without
|
||||
specified Strategy, StrategyContext will take care to retrieve default
|
||||
Strategy for this Goal.
|
||||
|
||||
By design, whole AuditHandler class passes current Audit as an argument of
|
||||
many of its methods. It would be convenient to have current Audit as a field of
|
||||
AuditHandler class. Also, it is good design decision, because it's true OOP
|
||||
paradigm. To sum up, we propose to remove all these arguments and replace
|
||||
them with class field.
|
||||
|
||||
As a result, we can get Planner for current Strategy without adding new
|
||||
argument to AuditHandler.planner() or storing name of Strategy in additional
|
||||
field.
|
||||
|
||||
Alternatives
|
||||
------------
|
||||
|
||||
Alternatively, we could pass Planner name as argument during creation of
|
||||
AuditTemplate.
|
||||
|
||||
As an alternative to changing signatures of AuditHandler methods we could add a
|
||||
new field only for Strategy name.
|
||||
|
||||
Data model impact
|
||||
-----------------
|
||||
|
||||
None
|
||||
|
||||
REST API impact
|
||||
---------------
|
||||
|
||||
None
|
||||
|
||||
Security impact
|
||||
---------------
|
||||
|
||||
None
|
||||
|
||||
Notifications impact
|
||||
--------------------
|
||||
|
||||
None
|
||||
|
||||
Other end user impact
|
||||
---------------------
|
||||
|
||||
None
|
||||
|
||||
Performance Impact
|
||||
------------------
|
||||
|
||||
None
|
||||
|
||||
Other deployer impact
|
||||
---------------------
|
||||
|
||||
None
|
||||
|
||||
Developer impact
|
||||
----------------
|
||||
|
||||
Signature of PlannerManager.load() method changes.
|
||||
AuditHandler methods change their signatures, 'audit' argument would be
|
||||
replaced with same class field.
|
||||
|
||||
|
||||
Implementation
|
||||
==============
|
||||
|
||||
Assignee(s)
|
||||
-----------
|
||||
|
||||
Primary assignee:
|
||||
Egor Panfilov <erakli>
|
||||
|
||||
Work Items
|
||||
----------
|
||||
|
||||
* Refactor DefaultStrategyContext.do_execute_strategy() and add
|
||||
select_strategy() method
|
||||
* Add 'planner' property to BaseStrategy
|
||||
* Replace PlannerManager with PlannerLoader in AuditHandler
|
||||
* Rewrite AuditHandler methods so that 'audit' argument would be replaced
|
||||
with class' field
|
||||
|
||||
|
||||
Dependencies
|
||||
============
|
||||
|
||||
https://blueprints.launchpad.net/watcher/+spec/planner-storage-action-plan
|
||||
|
||||
|
||||
Testing
|
||||
=======
|
||||
|
||||
Tests with different Planners assigned to different Strategies should be
|
||||
implemented.
|
||||
|
||||
|
||||
Documentation Impact
|
||||
====================
|
||||
|
||||
Documentation should be updated to explain how to set 'planner' option.
|
||||
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
None
|
||||
|
||||
|
||||
History
|
||||
=======
|
||||
|
||||
None
|
||||
|
||||
|
||||
.. _Actions: https://docs.openstack.org/watcher/latest/glossary.html#action
|
||||
.. _Strategy: https://docs.openstack.org/watcher/latest/glossary.html#strategy
|
||||
.. _Solutions: https://docs.openstack.org/watcher/latest/glossary.html#solution
|
||||
.. _Planner: https://docs.openstack.org/watcher/latest/glossary.html#watcher-planner
|
||||
.. _Watcher Planner: https://docs.openstack.org/watcher/latest/glossary.html#watcher-planner
|
Loading…
Reference in New Issue
Block a user