Browse Source

Decoupling magnum service from periodic task

Liberty tech-debt-bug

Magnum service was initially utilizing periodic task within magnum
conductor. This commit lays out independent periodic framework for
magnum service, by decoupling from periodic task.

Change-Id: Ie0e725b75069309a9fa783f77c1a454f9dae549e
Partial-Bug: 1500998
changes/99/246599/4
Surojit Pathak 7 years ago
parent
commit
d024bc60c4
  1. 5
      magnum/common/rpc_service.py
  2. 32
      magnum/service/periodic.py
  3. 63
      magnum/servicegroup/magnum_service_periodic.py
  4. 69
      magnum/tests/unit/service/test_periodic.py
  5. 0
      magnum/tests/unit/servicegroup/__init__.py
  6. 76
      magnum/tests/unit/servicegroup/test_magnum_service.py

5
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):

32
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

63
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)

69
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)

0
magnum/tests/unit/servicegroup/__init__.py

76
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)
Loading…
Cancel
Save