diff --git a/magnum/common/rpc_service.py b/magnum/common/rpc_service.py index 31a8ce7954..dbb6c96056 100644 --- a/magnum/common/rpc_service.py +++ b/magnum/common/rpc_service.py @@ -22,6 +22,7 @@ from oslo_service import service from magnum.common import rpc from magnum.objects import base as objects_base from magnum.service import periodic +from magnum.servicegroup import magnum_service_periodic as servicegroup # NOTE(paulczar): @@ -69,8 +70,10 @@ class Service(service.Service): self.binary = binary def start(self): + # NOTE(suro-patz): The parent class has created a threadgroup, already if CONF.periodic_enable: - self.tg = periodic.setup(CONF, self.binary) + periodic.setup(CONF, self.tg) + servicegroup.setup(CONF, self.binary, self.tg) self._server.start() def wait(self): diff --git a/magnum/service/periodic.py b/magnum/service/periodic.py index aa31689f16..23436b9a91 100644 --- a/magnum/service/periodic.py +++ b/magnum/service/periodic.py @@ -18,7 +18,6 @@ import six from oslo_log import log from oslo_service import periodic_task -from oslo_service import threadgroup from magnum.common import clients from magnum.common import context @@ -61,33 +60,10 @@ class MagnumPeriodicTasks(periodic_task.PeriodicTasks): ''' - def __init__(self, conf, binary): - self.magnum_service_ref = None - self.host = conf.host - self.binary = binary + def __init__(self, conf): super(MagnumPeriodicTasks, self).__init__(conf) self.notifier = rpc.get_notifier() - @periodic_task.periodic_task(run_immediately=True) - @set_context - def update_magnum_service(self, ctx): - LOG.debug('Update magnum_service') - if self.magnum_service_ref: - self.magnum_service_ref.report_state_up(ctx) - else: - self.magnum_service_ref = \ - objects.MagnumService.get_by_host_and_binary( - ctx, self.host, self.binary) - if self.magnum_service_ref is None: - magnum_service_dict = { - 'host': self.host, - 'binary': self.binary - } - self.magnum_service_ref = objects.MagnumService( - ctx, **magnum_service_dict) - self.magnum_service_ref.create(ctx) - self.magnum_service_ref.report_state_up(ctx) - @periodic_task.periodic_task(run_immediately=True) @set_context def sync_bay_status(self, ctx): @@ -210,11 +186,9 @@ class MagnumPeriodicTasks(periodic_task.PeriodicTasks): message) -def setup(conf, binary): - tg = threadgroup.ThreadGroup() - pt = MagnumPeriodicTasks(conf, binary) +def setup(conf, tg): + pt = MagnumPeriodicTasks(conf) tg.add_dynamic_timer( pt.run_periodic_tasks, periodic_interval_max=conf.periodic_interval_max, context=None) - return tg diff --git a/magnum/servicegroup/magnum_service_periodic.py b/magnum/servicegroup/magnum_service_periodic.py new file mode 100644 index 0000000000..b18407df62 --- /dev/null +++ b/magnum/servicegroup/magnum_service_periodic.py @@ -0,0 +1,63 @@ +# Copyright 2015 - Yahoo! Inc. +# +# 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. + +"""Magnum Service Layer""" + +from oslo_log import log +from oslo_service import periodic_task + +from magnum import objects +from magnum.service import periodic + + +LOG = log.getLogger(__name__) + + +class MagnumServicePeriodicTasks(periodic_task.PeriodicTasks): + '''Magnum periodic Task class + + Any periodic task job need to be added into this class + ''' + + def __init__(self, conf, binary): + self.magnum_service_ref = None + self.host = conf.host + self.binary = binary + super(MagnumServicePeriodicTasks, self).__init__(conf) + + @periodic_task.periodic_task(run_immediately=True) + @periodic.set_context + def update_magnum_service(self, ctx): + LOG.debug('Update magnum_service') + if self.magnum_service_ref is None: + self.magnum_service_ref = \ + objects.MagnumService.get_by_host_and_binary( + ctx, self.host, self.binary) + if self.magnum_service_ref is None: + magnum_service_dict = { + 'host': self.host, + 'binary': self.binary + } + self.magnum_service_ref = objects.MagnumService( + ctx, **magnum_service_dict) + self.magnum_service_ref.create(ctx) + self.magnum_service_ref.report_state_up(ctx) + + +def setup(conf, binary, tg): + pt = MagnumServicePeriodicTasks(conf, binary) + tg.add_dynamic_timer( + pt.run_periodic_tasks, + periodic_interval_max=conf.periodic_interval_max, + context=None) diff --git a/magnum/tests/unit/service/test_periodic.py b/magnum/tests/unit/service/test_periodic.py index 3833a899fb..91a498f210 100644 --- a/magnum/tests/unit/service/test_periodic.py +++ b/magnum/tests/unit/service/test_periodic.py @@ -51,14 +51,6 @@ class PeriodicTestCase(base.TestCase): self.bay3 = objects.Bay(ctx, **bay3) self.bay4 = objects.Bay(ctx, **bay4) - mock_magnum_service_refresh = mock.Mock() - - class FakeMS(object): - report_state_up = mock_magnum_service_refresh - - self.fake_ms = FakeMS() - self.fake_ms_refresh = mock_magnum_service_refresh - @mock.patch.object(objects.Bay, 'list') @mock.patch('magnum.common.clients.OpenStackClients') @mock.patch.object(dbapi.Connection, 'destroy_bay') @@ -79,8 +71,7 @@ class PeriodicTestCase(base.TestCase): mock_keystone_client.client.project_id = "fake_project" mock_osc.keystone.return_value = mock_keystone_client - periodic.MagnumPeriodicTasks(CONF, - 'fake-conductor').sync_bay_status(None) + periodic.MagnumPeriodicTasks(CONF).sync_bay_status(None) self.assertEqual(bay_status.CREATE_COMPLETE, self.bay1.status) self.assertEqual('fake_reason_11', self.bay1.status_reason) @@ -102,8 +93,7 @@ class PeriodicTestCase(base.TestCase): mock_osc = mock_oscc.return_value mock_osc.heat.return_value = mock_heat_client mock_bay_list.return_value = [self.bay1, self.bay2, self.bay3] - periodic.MagnumPeriodicTasks(CONF, - 'fake-conductor').sync_bay_status(None) + periodic.MagnumPeriodicTasks(CONF).sync_bay_status(None) self.assertEqual(bay_status.CREATE_IN_PROGRESS, self.bay1.status) self.assertEqual(bay_status.DELETE_IN_PROGRESS, self.bay2.status) @@ -126,8 +116,7 @@ class PeriodicTestCase(base.TestCase): mock_keystone_client.client.project_id = "fake_project" mock_osc.keystone.return_value = mock_keystone_client - periodic.MagnumPeriodicTasks(CONF, - 'fake-conductor').sync_bay_status(None) + periodic.MagnumPeriodicTasks(CONF).sync_bay_status(None) self.assertEqual(bay_status.CREATE_FAILED, self.bay1.status) self.assertEqual('Stack with id 11 not found in Heat.', @@ -137,46 +126,6 @@ class PeriodicTestCase(base.TestCase): self.assertEqual('Stack with id 33 not found in Heat.', self.bay3.status_reason) - @mock.patch.object(objects.MagnumService, 'get_by_host_and_binary') - @mock.patch.object(objects.MagnumService, 'create') - @mock.patch.object(objects.MagnumService, 'report_state_up') - def test_update_magnum_service_firsttime(self, - mock_ms_refresh, - mock_ms_create, - mock_ms_get - ): - periodic_a = periodic.MagnumPeriodicTasks(CONF, 'fake-conductor') - mock_ms_get.return_value = None - - periodic_a.update_magnum_service(None) - - mock_ms_get.assert_called_once_with(mock.ANY, periodic_a.host, - periodic_a.binary) - mock_ms_create.assert_called_once_with(mock.ANY) - mock_ms_refresh.assert_called_once_with(mock.ANY) - - @mock.patch.object(objects.MagnumService, 'get_by_host_and_binary') - @mock.patch.object(objects.MagnumService, 'create') - def test_update_magnum_service_on_restart(self, - mock_ms_create, - mock_ms_get): - periodic_a = periodic.MagnumPeriodicTasks(CONF, 'fake-conductor') - mock_ms_get.return_value = self.fake_ms - - periodic_a.update_magnum_service(None) - - mock_ms_get.assert_called_once_with(mock.ANY, periodic_a.host, - periodic_a.binary) - self.fake_ms_refresh.assert_called_once_with(mock.ANY) - - def test_update_magnum_service_regular(self): - periodic_a = periodic.MagnumPeriodicTasks(CONF, 'fake-conductor') - periodic_a.magnum_service_ref = self.fake_ms - - periodic_a.update_magnum_service(None) - - self.fake_ms_refresh.assert_called_once_with(mock.ANY) - @mock.patch('magnum.conductor.monitors.create_monitor') @mock.patch('magnum.objects.Bay.list') @mock.patch('magnum.common.rpc.get_notifier') @@ -195,8 +144,7 @@ class PeriodicTestCase(base.TestCase): monitor.get_metric_unit.return_value = '%' mock_create_monitor.return_value = monitor - periodic.MagnumPeriodicTasks( - CONF, 'fake-conductor')._send_bay_metrics(self.context) + periodic.MagnumPeriodicTasks(CONF)._send_bay_metrics(self.context) expected_event_type = 'magnum.bay.metrics.update' expected_metrics = [ @@ -239,8 +187,7 @@ class PeriodicTestCase(base.TestCase): "error on computing metric") mock_create_monitor.return_value = monitor - periodic.MagnumPeriodicTasks( - CONF, 'fake-conductor')._send_bay_metrics(self.context) + periodic.MagnumPeriodicTasks(CONF)._send_bay_metrics(self.context) expected_event_type = 'magnum.bay.metrics.update' expected_msg = { @@ -268,8 +215,7 @@ class PeriodicTestCase(base.TestCase): monitor.pull_data.side_effect = Exception("error on pulling data") mock_create_monitor.return_value = monitor - periodic.MagnumPeriodicTasks( - CONF, 'fake-conductor')._send_bay_metrics(self.context) + periodic.MagnumPeriodicTasks(CONF)._send_bay_metrics(self.context) self.assertEqual(1, mock_create_monitor.call_count) self.assertEqual(0, notifier.info.call_count) @@ -287,8 +233,7 @@ class PeriodicTestCase(base.TestCase): mock_bay_list.return_value = [self.bay4] mock_create_monitor.return_value = None - periodic.MagnumPeriodicTasks( - CONF, 'fake-conductor')._send_bay_metrics(self.context) + periodic.MagnumPeriodicTasks(CONF)._send_bay_metrics(self.context) self.assertEqual(1, mock_create_monitor.call_count) self.assertEqual(0, notifier.info.call_count) diff --git a/magnum/tests/unit/servicegroup/__init__.py b/magnum/tests/unit/servicegroup/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/magnum/tests/unit/servicegroup/test_magnum_service.py b/magnum/tests/unit/servicegroup/test_magnum_service.py new file mode 100644 index 0000000000..ef0b5745d3 --- /dev/null +++ b/magnum/tests/unit/servicegroup/test_magnum_service.py @@ -0,0 +1,76 @@ +# Copyright 2015 - Yahoo! Inc. +# +# 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 + +from magnum.common.rpc_service import CONF +from magnum import objects +from magnum.servicegroup import magnum_service_periodic as periodic +from magnum.tests import base + + +class MagnumServicePeriodicTestCase(base.TestCase): + + def setUp(self): + super(MagnumServicePeriodicTestCase, self).setUp() + mock_magnum_service_refresh = mock.Mock() + + class FakeMS(object): + report_state_up = mock_magnum_service_refresh + + self.fake_ms = FakeMS() + self.fake_ms_refresh = mock_magnum_service_refresh + + @mock.patch.object(objects.MagnumService, 'get_by_host_and_binary') + @mock.patch.object(objects.MagnumService, 'create') + @mock.patch.object(objects.MagnumService, 'report_state_up') + def test_update_magnum_service_firsttime(self, + mock_ms_refresh, + mock_ms_create, + mock_ms_get + ): + p_task = periodic.MagnumServicePeriodicTasks(CONF, + 'fake-conductor') + mock_ms_get.return_value = None + + p_task.update_magnum_service(None) + + mock_ms_get.assert_called_once_with(mock.ANY, p_task.host, + p_task.binary) + mock_ms_create.assert_called_once_with(mock.ANY) + mock_ms_refresh.assert_called_once_with(mock.ANY) + + @mock.patch.object(objects.MagnumService, 'get_by_host_and_binary') + @mock.patch.object(objects.MagnumService, 'create') + def test_update_magnum_service_on_restart(self, + mock_ms_create, + mock_ms_get): + p_task = periodic.MagnumServicePeriodicTasks(CONF, + 'fake-conductor') + mock_ms_get.return_value = self.fake_ms + + p_task.update_magnum_service(None) + + mock_ms_get.assert_called_once_with(mock.ANY, p_task.host, + p_task.binary) + self.fake_ms_refresh.assert_called_once_with(mock.ANY) + + def test_update_magnum_service_regular(self): + p_task = periodic.MagnumServicePeriodicTasks(CONF, + 'fake-conductor') + p_task.magnum_service_ref = self.fake_ms + + p_task.update_magnum_service(None) + + self.fake_ms_refresh.assert_called_once_with(mock.ANY)