Create OpenStackClients convenience class
The OpenStackClients class provides a convenient way to create and cache client instances. The idea behind this code comes from Magnum [0]. The OpenStackClients class will act as the manager of other project's clients, providing an easy way to fetch instances of said clients. This will allow the clients to be cached. An instance of OpenStackClients is created for every call that comes into the decision engine and the applier, using the request context to pass needed (domain id) parameters to get a Keystone session. This instance should be shared as much as possible to avoid additional unneccessary connections to the other services. This class will also allow for the version of each client to be configurable via the watcher.conf file. The method by which a Keystone session is also changed to use the keystoneauth1.loading library. In order to avoid DuplicateOptErrors with the keystone_authtoken group used for the keystonemiddleware in the API code, a new conf group named "watcher_clients_auth" is created. A typical configuration using a password authentication scheme will look like: [watcher_clients_auth] auth_type = password auth_url = http://<server-ip>:<port> username = <username> password = <password> project_domain_id = default user_domain_id = default [0]: https://github.com/openstack/magnum/blob/master/magnum/common/clients.py DocImpact Change-Id: Iab9d0b304099686da2e9e2b19e8b1de4332ff378 Implements: blueprint external-api-versioning Closes-Bug: #1530790 Closes-Bug: #1539670 Closes-Bug: #1522774
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
# limitations under the License.
|
||||
from oslo_log import log
|
||||
|
||||
from watcher.common import clients
|
||||
from watcher.decision_engine.strategy.context.base import BaseStrategyContext
|
||||
from watcher.decision_engine.strategy.selection.default import \
|
||||
DefaultStrategySelector
|
||||
@@ -47,15 +48,17 @@ class DefaultStrategyContext(BaseStrategyContext):
|
||||
audit_template = objects.\
|
||||
AuditTemplate.get_by_id(request_context, audit.audit_template_id)
|
||||
|
||||
osc = clients.OpenStackClients()
|
||||
|
||||
# todo(jed) retrieve in audit_template parameters (threshold,...)
|
||||
# todo(jed) create ActionPlan
|
||||
collector_manager = self.collector.get_cluster_model_collector()
|
||||
collector_manager = self.collector.get_cluster_model_collector(osc=osc)
|
||||
|
||||
# todo(jed) remove call to get_latest_cluster_data_model
|
||||
cluster_data_model = collector_manager.get_latest_cluster_data_model()
|
||||
|
||||
selected_strategy = self.strategy_selector. \
|
||||
define_from_goal(audit_template.goal)
|
||||
selected_strategy = self.strategy_selector.define_from_goal(
|
||||
audit_template.goal, osc=osc)
|
||||
|
||||
# todo(jed) add parameters and remove cluster_data_model
|
||||
return selected_strategy.execute(cluster_data_model)
|
||||
|
||||
@@ -48,11 +48,12 @@ class DefaultStrategySelector(base.BaseSelector):
|
||||
super(DefaultStrategySelector, self).__init__()
|
||||
self.strategy_loader = default.DefaultStrategyLoader()
|
||||
|
||||
def define_from_goal(self, goal_name):
|
||||
def define_from_goal(self, goal_name, osc=None):
|
||||
""":param osc: an OpenStackClients instance"""
|
||||
strategy_to_load = None
|
||||
try:
|
||||
strategy_to_load = CONF.watcher_goals.goals[goal_name]
|
||||
return self.strategy_loader.load(strategy_to_load)
|
||||
return self.strategy_loader.load(strategy_to_load, osc=osc)
|
||||
except KeyError as exc:
|
||||
LOG.exception(exc)
|
||||
raise exception.WatcherException(
|
||||
|
||||
@@ -33,10 +33,11 @@ provided as well.
|
||||
"""
|
||||
|
||||
import abc
|
||||
|
||||
from oslo_log import log
|
||||
import six
|
||||
|
||||
|
||||
from watcher.common import clients
|
||||
from watcher.decision_engine.solution.default import DefaultSolution
|
||||
from watcher.decision_engine.strategy.common.level import StrategyLevel
|
||||
|
||||
@@ -51,7 +52,8 @@ class BaseStrategy(object):
|
||||
Solution for a given Goal.
|
||||
"""
|
||||
|
||||
def __init__(self, name=None, description=None):
|
||||
def __init__(self, name=None, description=None, osc=None):
|
||||
""":param osc: an OpenStackClients instance"""
|
||||
self._name = name
|
||||
self.description = description
|
||||
# default strategy level
|
||||
@@ -59,6 +61,7 @@ class BaseStrategy(object):
|
||||
self._cluster_state_collector = None
|
||||
# the solution given by the strategy
|
||||
self._solution = DefaultSolution()
|
||||
self._osc = osc
|
||||
|
||||
@abc.abstractmethod
|
||||
def execute(self, model):
|
||||
@@ -70,6 +73,12 @@ class BaseStrategy(object):
|
||||
:rtype: :class:`watcher.decision_engine.solution.base.BaseSolution`
|
||||
"""
|
||||
|
||||
@property
|
||||
def osc(self):
|
||||
if not self._osc:
|
||||
self._osc = clients.OpenStackClients()
|
||||
return self._osc
|
||||
|
||||
@property
|
||||
def solution(self):
|
||||
return self._solution
|
||||
|
||||
@@ -41,7 +41,8 @@ class BasicConsolidation(BaseStrategy):
|
||||
MIGRATION = "migrate"
|
||||
CHANGE_NOVA_SERVICE_STATE = "change_nova_service_state"
|
||||
|
||||
def __init__(self, name=DEFAULT_NAME, description=DEFAULT_DESCRIPTION):
|
||||
def __init__(self, name=DEFAULT_NAME, description=DEFAULT_DESCRIPTION,
|
||||
osc=None):
|
||||
"""Basic offline Consolidation using live migration
|
||||
|
||||
The basic consolidation algorithm has several limitations.
|
||||
@@ -68,8 +69,9 @@ class BasicConsolidation(BaseStrategy):
|
||||
|
||||
:param name: the name of the strategy
|
||||
:param description: a description of the strategy
|
||||
:param osc: an OpenStackClients object
|
||||
"""
|
||||
super(BasicConsolidation, self).__init__(name, description)
|
||||
super(BasicConsolidation, self).__init__(name, description, osc)
|
||||
|
||||
# set default value for the number of released nodes
|
||||
self.number_of_released_nodes = 0
|
||||
@@ -102,7 +104,7 @@ class BasicConsolidation(BaseStrategy):
|
||||
@property
|
||||
def ceilometer(self):
|
||||
if self._ceilometer is None:
|
||||
self._ceilometer = CeilometerClusterHistory()
|
||||
self._ceilometer = CeilometerClusterHistory(osc=self.osc)
|
||||
return self._ceilometer
|
||||
|
||||
@ceilometer.setter
|
||||
|
||||
@@ -30,8 +30,9 @@ class DummyStrategy(BaseStrategy):
|
||||
NOP = "nop"
|
||||
SLEEP = "sleep"
|
||||
|
||||
def __init__(self, name=DEFAULT_NAME, description=DEFAULT_DESCRIPTION):
|
||||
super(DummyStrategy, self).__init__(name, description)
|
||||
def __init__(self, name=DEFAULT_NAME, description=DEFAULT_DESCRIPTION,
|
||||
osc=None):
|
||||
super(DummyStrategy, self).__init__(name, description, osc)
|
||||
|
||||
def execute(self, model):
|
||||
parameters = {'message': 'hello World'}
|
||||
|
||||
@@ -40,7 +40,8 @@ class OutletTempControl(BaseStrategy):
|
||||
|
||||
MIGRATION = "migrate"
|
||||
|
||||
def __init__(self, name=DEFAULT_NAME, description=DEFAULT_DESCRIPTION):
|
||||
def __init__(self, name=DEFAULT_NAME, description=DEFAULT_DESCRIPTION,
|
||||
osc=None):
|
||||
"""[PoC]Outlet temperature control using live migration
|
||||
|
||||
It is a migration strategy based on the Outlet Temperature of physical
|
||||
@@ -67,8 +68,9 @@ class OutletTempControl(BaseStrategy):
|
||||
|
||||
:param name: the name of the strategy
|
||||
:param description: a description of the strategy
|
||||
:param osc: an OpenStackClients object
|
||||
"""
|
||||
super(OutletTempControl, self).__init__(name, description)
|
||||
super(OutletTempControl, self).__init__(name, description, osc)
|
||||
# the migration plan will be triggered when the outlet temperature
|
||||
# reaches threshold
|
||||
# TODO(zhenzanz): Threshold should be configurable for each audit
|
||||
@@ -79,7 +81,7 @@ class OutletTempControl(BaseStrategy):
|
||||
@property
|
||||
def ceilometer(self):
|
||||
if self._ceilometer is None:
|
||||
self._ceilometer = CeilometerClusterHistory()
|
||||
self._ceilometer = CeilometerClusterHistory(osc=self.osc)
|
||||
return self._ceilometer
|
||||
|
||||
@ceilometer.setter
|
||||
|
||||
Reference in New Issue
Block a user