Watcher plugins table in Guru meditation reports

In this changeset, I added the list of all the available plugins
for the current instance of any given Watcher service.

Partially Implements: blueprint plugins-parameters

Change-Id: I58c9724a229712b0322a578f0f89a61b38dfd80a
This commit is contained in:
Vincent Françoise 2016-05-24 16:53:44 +02:00
parent 5aa6b16238
commit e6f147d81d
7 changed files with 79 additions and 16 deletions

View File

@ -21,12 +21,9 @@ import sys
from oslo_config import cfg
from oslo_log import log as logging
from oslo_reports import guru_meditation_report as gmr
from watcher._i18n import _
from watcher._i18n import _LI
from watcher.common import service
from watcher import version
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
@ -35,8 +32,6 @@ CONF = cfg.CONF
def main():
service.prepare_service(sys.argv)
gmr.TextGuruMeditation.setup_autorun(version)
host, port = cfg.CONF.api.host, cfg.CONF.api.port
protocol = "http" if not CONF.api.enable_ssl_api else "https"
# Build and start the WSGI app
@ -44,11 +39,11 @@ def main():
'watcher-api', CONF.api.enable_ssl_api)
if host == '0.0.0.0':
LOG.info(_('serving on 0.0.0.0:%(port)s, '
'view at %(protocol)s://127.0.0.1:%(port)s') %
LOG.info(_LI('serving on 0.0.0.0:%(port)s, '
'view at %(protocol)s://127.0.0.1:%(port)s') %
dict(protocol=protocol, port=port))
else:
LOG.info(_('serving on %(protocol)s://%(host)s:%(port)s') %
LOG.info(_LI('serving on %(protocol)s://%(host)s:%(port)s') %
dict(protocol=protocol, host=host, port=port))
launcher = service.process_launcher()

View File

@ -22,13 +22,11 @@ import sys
from oslo_config import cfg
from oslo_log import log as logging
from oslo_reports import guru_meditation_report as gmr
from oslo_service import service
from watcher._i18n import _LI
from watcher.applier import manager
from watcher.common import service as watcher_service
from watcher import version
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
@ -36,7 +34,6 @@ CONF = cfg.CONF
def main():
watcher_service.prepare_service(sys.argv)
gmr.TextGuruMeditation.setup_autorun(version)
LOG.info(_LI('Starting Watcher Applier service in PID %s'), os.getpid())

View File

@ -22,14 +22,12 @@ import sys
from oslo_config import cfg
from oslo_log import log as logging
from oslo_reports import guru_meditation_report as gmr
from oslo_service import service
from watcher._i18n import _LI
from watcher.common import service as watcher_service
from watcher.decision_engine import manager
from watcher.decision_engine import sync
from watcher import version
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
@ -37,7 +35,6 @@ CONF = cfg.CONF
def main():
watcher_service.prepare_service(sys.argv)
gmr.TextGuruMeditation.setup_autorun(version)
LOG.info(_LI('Starting Watcher Decision Engine service in PID %s'),
os.getpid())

View File

@ -22,6 +22,7 @@ from oslo_config import cfg
from oslo_log import _options
from oslo_log import log
import oslo_messaging as om
from oslo_reports import guru_meditation_report as gmr
from oslo_reports import opts as gmr_opts
from oslo_service import service
from oslo_service import wsgi
@ -33,6 +34,8 @@ from watcher.common.messaging.events import event_dispatcher as dispatcher
from watcher.common.messaging import messaging_handler
from watcher.common import rpc
from watcher.objects import base
from watcher import opts
from watcher import version
service_opts = [
cfg.IntOpt('periodic_interval',
@ -219,3 +222,6 @@ def prepare_service(argv=(), conf=cfg.CONF):
default_log_levels=_DEFAULT_LOG_LEVELS)
log.setup(conf, 'python-watcher')
conf.log_opt_values(LOG, logging.DEBUG)
gmr.TextGuruMeditation.register_section(_('Plugins'), opts.show_plugins)
gmr.TextGuruMeditation.setup_autorun(version)

View File

@ -118,6 +118,14 @@ def is_hostname_safe(hostname):
:returns: True if valid. False if not.
"""
m = '^[a-z0-9]([a-z0-9\-]{0,61}[a-z0-9])?$'
m = r'^[a-z0-9]([a-z0-9\-]{0,61}[a-z0-9])?$'
return (isinstance(hostname, six.string_types) and
(re.match(m, hostname) is not None))
def get_cls_import_path(cls):
"""Return the import path of a given class"""
module = cls.__module__
if module is None or module == str.__module__:
return cls.__name__
return module + '.' + cls.__name__

View File

@ -16,6 +16,7 @@
# limitations under the License.
from keystoneauth1 import loading as ka_loading
import prettytable as ptable
import watcher.api.app
from watcher.applier.actions.loading import default as action_loader
@ -23,6 +24,7 @@ from watcher.applier import manager as applier_manager
from watcher.applier.workflow_engine.loading import default as \
workflow_engine_loader
from watcher.common import clients
from watcher.common import utils
from watcher.decision_engine import manager as decision_engine_manger
from watcher.decision_engine.planner.loading import default as planner_loader
from watcher.decision_engine.planner import manager as planner_manager
@ -73,3 +75,26 @@ def list_plugin_opts():
(plugin_loader.get_entry_name(plugin_name), plugin_opts))
return plugins_opts
def _show_plugins_ascii_table(rows):
headers = ["Namespace", "Plugin name", "Import path"]
table = ptable.PrettyTable(field_names=headers)
for row in rows:
table.add_row(row)
return table.get_string()
def show_plugins():
rows = []
for plugin_loader_cls in PLUGIN_LOADERS:
plugin_loader = plugin_loader_cls()
plugins_map = plugin_loader.list_available()
rows += [
(plugin_loader.get_entry_name(plugin_name),
plugin_name,
utils.get_cls_import_path(plugin_cls))
for plugin_name, plugin_cls in plugins_map.items()]
return _show_plugins_ascii_table(rows)

View File

@ -108,3 +108,38 @@ class TestListOpts(base.TestCase):
strategy_opts = result_map['watcher_strategies.STRATEGY_1']
self.assertEqual(['test_opt'], [opt.name for opt in strategy_opts])
class TestPlugins(base.TestCase):
def test_show_plugins(self):
# Set up the fake Stevedore extensions
fake_extmanager_call = extension.ExtensionManager.make_test_instance(
extensions=[extension.Extension(
name=fake_strategies.FakeDummy1Strategy1.get_name(),
entry_point="%s:%s" % (
fake_strategies.FakeDummy1Strategy1.__module__,
fake_strategies.FakeDummy1Strategy1.__name__),
plugin=fake_strategies.FakeDummy1Strategy1,
obj=None,
)],
namespace="watcher_strategies",
)
def m_list_available(namespace):
if namespace == "watcher_strategies":
return fake_extmanager_call
else:
return extension.ExtensionManager.make_test_instance(
extensions=[], namespace=namespace)
with mock.patch.object(extension, "ExtensionManager") as m_ext_manager:
with mock.patch.object(
opts, "_show_plugins_ascii_table"
) as m_show:
m_ext_manager.side_effect = m_list_available
opts.show_plugins()
m_show.assert_called_once_with(
[('watcher_strategies.STRATEGY_1', 'STRATEGY_1',
'watcher.tests.decision_engine.'
'fake_strategies.FakeDummy1Strategy1')])