Make default Planner generic to handle new action

Currently we have to amend the code of the Planner
for each new added Watcher Action. This patch set will
modifying the DefaultPlanner class and  leverage the
plugins-parameters blueprint so that we can configure
weights via the configuration file.

Documentation and unittest also be update in this patch.

Co-Authored-By: Vincent Françoise <vincent.francoise@b-com.com>

Change-Id: Ib794488fcafd1e153a7d7b1f7253686136501872
blueprint: configurable-weights-default-planner
This commit is contained in:
jinquanni
2016-07-07 20:12:53 +08:00
parent b1c6ea71a4
commit b4c5e2bb81
6 changed files with 81 additions and 12 deletions

View File

@@ -50,6 +50,7 @@ class TestCase(BaseTestCase):
def setUp(self):
super(TestCase, self).setUp()
self.useFixture(conf_fixture.ConfReloadFixture())
self.app = testing.load_test_app(os.path.join(
os.path.dirname(__file__),
'config.py'

View File

@@ -39,3 +39,22 @@ class ConfFixture(fixtures.Fixture):
self.conf.set_default('verbose', True)
config.parse_args([], default_config_files=[])
self.addCleanup(self.conf.reset)
class ConfReloadFixture(ConfFixture):
"""Fixture to manage reloads of conf settings."""
def __init__(self, conf=cfg.CONF):
self.conf = conf
self._original_parse_cli_opts = self.conf._parse_cli_opts
def _fake_parser(self, *args, **kw):
return cfg.ConfigOpts._parse_cli_opts(self.conf, [])
def _restore_parser(self):
self.conf._parse_cli_opts = self._original_parse_cli_opts
def setUp(self):
super(ConfReloadFixture, self).setUp()
self.conf._parse_cli_opts = self._fake_parser
self.addCleanup(self._restore_parser)

View File

@@ -76,9 +76,9 @@ class TestActionScheduling(base.DbTestCase):
with mock.patch.object(
pbase.DefaultPlanner, "create_action",
wraps=default_planner.create_action) as m_create_action:
action_plan = default_planner.schedule(
self.context, audit.id, solution
)
default_planner.config.weights = {'migrate': 3}
action_plan = default_planner.schedule(self.context,
audit.id, solution)
self.assertIsNotNone(action_plan.uuid)
self.assertEqual(1, m_create_action.call_count)
@@ -107,9 +107,9 @@ class TestActionScheduling(base.DbTestCase):
with mock.patch.object(
pbase.DefaultPlanner, "create_action",
wraps=default_planner.create_action) as m_create_action:
action_plan = default_planner.schedule(
self.context, audit.id, solution
)
default_planner.config.weights = {'migrate': 3, 'nop': 0}
action_plan = default_planner.schedule(self.context,
audit.id, solution)
self.assertIsNotNone(action_plan.uuid)
self.assertEqual(2, m_create_action.call_count)
# check order
@@ -118,12 +118,45 @@ class TestActionScheduling(base.DbTestCase):
self.assertEqual("nop", actions[0].action_type)
self.assertEqual("migrate", actions[1].action_type)
def test_schedule_actions_with_unknown_action(self):
default_planner = pbase.DefaultPlanner(mock.Mock())
audit = db_utils.create_test_audit(uuid=utils.generate_uuid())
solution = dsol.DefaultSolution(
goal=mock.Mock(), strategy=mock.Mock())
parameters = {
"src_uuid_hypervisor": "server1",
"dst_uuid_hypervisor": "server2",
}
solution.add_action(action_type="migrate",
resource_id="b199db0c-1408-4d52-b5a5-5ca14de0ff36",
input_parameters=parameters)
solution.add_action(action_type="new_action_type",
resource_id="",
input_parameters={})
with mock.patch.object(
pbase.DefaultPlanner, "create_action",
wraps=default_planner.create_action) as m_create_action:
default_planner.config.weights = {'migrate': 0}
self.assertRaises(KeyError, default_planner.schedule,
self.context, audit.id, solution)
self.assertEqual(2, m_create_action.call_count)
class TestDefaultPlanner(base.DbTestCase):
def setUp(self):
super(TestDefaultPlanner, self).setUp()
self.default_planner = pbase.DefaultPlanner(mock.Mock())
self.default_planner.config.weights = {
'nop': 0,
'sleep': 1,
'change_nova_service_state': 2,
'migrate': 3
}
obj_utils.create_test_audit_template(self.context)
p = mock.patch.object(db_api.BaseConnection, 'create_action_plan')

View File

@@ -29,7 +29,7 @@ class TestListOpts(base.TestCase):
'api', 'watcher_decision_engine', 'watcher_applier',
'watcher_planner', 'nova_client', 'glance_client',
'cinder_client', 'ceilometer_client', 'neutron_client',
'watcher_clients_auth']
'watcher_clients_auth', 'watcher_planners.default']
def test_run_list_opts(self):
expected_sections = self.base_sections