Replace the old http url links with the lastest https ones according to the official OpenStack website. Change-Id: I1abd79bb80dae44ee2ba5946b8a375c7096b39d6
9.6 KiB
Build a new cluster data model collector
Watcher Decision Engine has an external cluster data model (CDM) plugin interface which gives anyone the ability to integrate an external cluster data model collector (CDMC) in order to extend the initial set of cluster data model collectors Watcher provides.
This section gives some guidelines on how to implement and integrate custom cluster data model collectors within Watcher.
Creating a new plugin
In order to create a new cluster data model collector, you have to:
- Extend the :py
~.base.BaseClusterDataModelCollector
class. - Implement its :py
~.BaseClusterDataModelCollector.execute
abstract method to return your entire cluster data model that this method should build. - Implement its :py
~.BaseClusterDataModelCollector.audit_scope_handler
abstract property to return your audit scope handler. - Implement its :py
~.Goal.notification_endpoints
abstract property to return the list of all the :py~.base.NotificationEndpoint
instances that will be responsible for handling incoming notifications in order to incrementally update your cluster data model.
First of all, you have to extend the ~.BaseClusterDataModelCollector
base class which
defines the :py~.BaseClusterDataModelCollector.execute
abstract
method you will have to implement. This method is responsible for
building an entire cluster data model.
Here is an example showing how you can write a plugin called
DummyClusterDataModelCollector
:
# Filepath = <PROJECT_DIR>/thirdparty/dummy.py
# Import path = thirdparty.dummy
from watcher.decision_engine.model import model_root
from watcher.decision_engine.model.collector import base
class DummyClusterDataModelCollector(base.BaseClusterDataModelCollector):
def execute(self):
= model_root.ModelRoot()
model # Do something here...
return model
@property
def audit_scope_handler(self):
return None
@property
def notification_endpoints(self):
return []
This implementation is the most basic one. So in order to get a
better understanding on how to implement a more advanced cluster data
model collector, have a look at the :py~.NovaClusterDataModelCollector
class.
Define a custom model
As you may have noticed in the above example, we are reusing an
existing model provided by Watcher. However, this model can be easily
customized by implementing a new class that would implement the :py~.Model
abstract base
class. Here below is simple example on how to proceed in implementing a
custom Model:
# Filepath = <PROJECT_DIR>/thirdparty/dummy.py
# Import path = thirdparty.dummy
from watcher.decision_engine.model import base as modelbase
from watcher.decision_engine.model.collector import base
class MyModel(modelbase.Model):
def to_string(self):
return 'MyModel'
class DummyClusterDataModelCollector(base.BaseClusterDataModelCollector):
def execute(self):
= MyModel()
model # Do something here...
return model
@property
def notification_endpoints(self):
return []
Here below is the abstract Model
class that every single
cluster data model should implement:
watcher.decision_engine.model.base.Model
Define configuration parameters
At this point, you have a fully functional cluster data model
collector. By default, cluster data model collectors define a
period
option (see :py~.BaseClusterDataModelCollector.get_config_opts
) that
corresponds to the interval of time between each synchronization of the
in-memory model.
However, in more complex implementation, you may want to define some
configuration options so one can tune the cluster data model collector
to your needs. To do so, you can implement the :py~.Loadable.get_config_opts
class method as followed:
from oslo_config import cfg
from watcher.decision_engine.model import model_root
from watcher.decision_engine.model.collector import base
class DummyClusterDataModelCollector(base.BaseClusterDataModelCollector):
def execute(self):
= model_root.ModelRoot()
model # Do something here...
return model
@property
def audit_scope_handler(self):
return None
@property
def notification_endpoints(self):
return []
@classmethod
def get_config_opts(cls):
return super(
+ [
DummyClusterDataModelCollector, cls).get_config_opts() 'test_opt', help="Demo Option.", default=0),
cfg.StrOpt(# 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}
(see section Register a new
entry point <register_new_cdmc_entrypoint>
). The namespace
for CDMC plugins is watcher_cluster_data_model_collectors
,
so in our case, the watcher.conf
configuration would have
to be modified as followed:
[watcher_cluster_data_model_collectors.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~.BaseClusterDataModelCollector.__init__
method.
Abstract Plugin Class
Here below is the abstract BaseClusterDataModelCollector
class that every single cluster data model collector should
implement:
watcher.decision_engine.model.collector.base.BaseClusterDataModelCollector
Register a new entry point
In order for the Watcher Decision Engine to load your new cluster
data model collector, the latter must be registered as a named entry
point under the watcher_cluster_data_model_collectors
entry
point namespace of your setup.py
file. If you are using pbr, this entry point
should be placed in your setup.cfg
file.
The name you give to your entry point has to be unique.
Here below is how to register
DummyClusterDataModelCollector
using pbr:
[entry_points]
watcher_cluster_data_model_collectors =
dummy = thirdparty.dummy:DummyClusterDataModelCollector
Add new notification endpoints
At this point, you have a fully functional cluster data model
collector. However, this CDMC is only refreshed periodically via a
background scheduler. As you may sometimes execute a strategy with a
stale CDM due to a high activity on your infrastructure, you can define
some notification endpoints that will be responsible for incrementally
updating the CDM based on notifications emitted by other services such
as Nova. To do so, you can implement and register a new
DummyEndpoint
notification endpoint regarding a
dummy
event as shown below:
from watcher.decision_engine.model import model_root
from watcher.decision_engine.model.collector import base
class DummyNotification(base.NotificationEndpoint):
@property
def filter_rule(self):
return filtering.NotificationFilter(
=r'.*',
publisher_id=r'^dummy$',
event_type
)
def info(self, ctxt, publisher_id, event_type, payload, metadata):
# Do some CDM modifications here...
pass
class DummyClusterDataModelCollector(base.BaseClusterDataModelCollector):
def execute(self):
= model_root.ModelRoot()
model # Do something here...
return model
@property
def notification_endpoints(self):
return [DummyNotification(self)]
Note that if the event you are trying to listen to is published by a
new service, you may have to also add a new topic Watcher will have to
subscribe to in the notification_topics
option of the
[watcher_decision_engine]
section.
Using cluster data model collector plugins
The Watcher Decision Engine service will automatically discover any installed plugins when it is restarted. If a Python package containing a custom plugin is installed within the same environment as Watcher, Watcher will automatically make that plugin available for use.
At this point, you can use your new cluster data model plugin in your
strategy plugin <implement_strategy_plugin>
by
using the :py~.BaseStrategy.collector_manager
property as
followed:
# [...]
= self.collector_manager.get_cluster_model_collector(
dummy_collector "dummy") # "dummy" is the name of the entry point we declared earlier
= dummy_collector.get_latest_cluster_data_model()
dummy_model # Do some stuff with this model