Expose trove conductor manager class as conf property

The current implementation of trove conductor hard-codes the conductor
manager class name in the cmd entry point thus not allowing it to be set
by consumers. This change exposes that classname on the conductor conf
so that consumers could plug-in their own manager class. Additionally
unit tests are provided to ensure a user defined and conductor manager
can be used in addition to the default trove conductor manager.

Change-Id: I6bf88dd9cf119f0eb6a197f4bda48c309511297e
Implements: blueprint pluggable-conductor-manager
This commit is contained in:
boden
2014-06-25 09:19:09 -04:00
parent 0a6de4300e
commit 87f0229e87
5 changed files with 100 additions and 2 deletions
+3
View File
@@ -32,3 +32,6 @@ rabbit_password=f7999d1955c5014aa32c
#rabbit_notification_topic = ['notifications']
rpc_backend = trove.openstack.common.rpc.impl_kombu
# The manager class to use for conductor. (string value)
conductor_manager = trove.conductor.manager.Manager
+2 -2
View File
@@ -20,9 +20,9 @@ def main(conf):
from trove.common.rpc import service as rpc_service
from trove.openstack.common import service as openstack_service
manager = 'trove.conductor.manager.Manager'
topic = conf.conductor_queue
server = rpc_service.RpcService(manager=manager, topic=topic)
server = rpc_service.RpcService(manager=conf.conductor_manager,
topic=topic)
launcher = openstack_service.launch(server,
workers=conf.trove_conductor_workers)
launcher.wait()
+2
View File
@@ -263,6 +263,8 @@ common_opts = [
'max_header_line may need to be increased when using '
'large tokens (typically those generated by the '
'Keystone v3 API with big service catalogs).'),
cfg.StrOpt('conductor_manager', default='trove.conductor.manager.Manager',
help='Qualified class name to use for conductor manager.')
]
# Datastore specific option groups
+22
View File
@@ -0,0 +1,22 @@
# Copyright 2014 IBM Corp.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
class FakeConf(object):
def __init__(self, conf_dict):
self._conf = conf_dict
def __getattr__(self, name):
return self._conf[name]
@@ -0,0 +1,71 @@
# Copyright 2014 IBM Corp.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import mock
import testtools
import trove.common.cfg as cfg
import trove.tests.fakes.conf as fake_conf
from trove.cmd import conductor as conductor_cmd
from trove.cmd import common as common_cmd
from trove.openstack.common import service as os_service
CONF = cfg.CONF
TROVE_UT = 'trove.tests.unittests'
def mocked_conf(manager):
return fake_conf.FakeConf({
'conductor_queue': 'conductor',
'conductor_manager': manager,
'trove_conductor_workers': 1,
'host': 'mockhost',
'report_interval': 1})
class NoopManager(object):
pass
class ConductorConfTests(testtools.TestCase):
def setUp(self):
super(ConductorConfTests, self).setUp()
def tearDown(self):
super(ConductorConfTests, self).tearDown()
def _test_manager(self, conf, rt_mgr_name):
def mock_launch(server, workers):
qualified_mgr = "%s.%s" % (server.manager_impl.__module__,
server.manager_impl.__class__.__name__)
self.assertEqual(rt_mgr_name, qualified_mgr, "Invalid manager")
return mock.MagicMock()
os_service.launch = mock_launch
common_cmd.initialize = mock.MagicMock(return_value=conf)
conductor_cmd.main()
def test_user_defined_manager(self):
qualified_mgr = TROVE_UT + ".conductor.test_conf.NoopManager"
self._test_manager(mocked_conf(qualified_mgr), qualified_mgr)
def test_default_manager(self):
qualified_mgr = "trove.conductor.manager.Manager"
self._test_manager(CONF, qualified_mgr)
def test_invalid_manager(self):
self.assertRaises(ImportError, self._test_manager,
mocked_conf('foo.bar.MissingMgr'),
'foo.bar.MissingMgr')