From bff4227aedce15a441737edd90f3c9628028fe50 Mon Sep 17 00:00:00 2001 From: Egor Panfilov Date: Tue, 3 Apr 2018 22:50:13 +0300 Subject: [PATCH] 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 --- .../approved/watcher-planner-selector.rst | 218 ++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 specs/rocky/approved/watcher-planner-selector.rst diff --git a/specs/rocky/approved/watcher-planner-selector.rst b/specs/rocky/approved/watcher-planner-selector.rst new file mode 100644 index 0000000..016e3da --- /dev/null +++ b/specs/rocky/approved/watcher-planner-selector.rst @@ -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 + +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