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
This commit is contained in:
parent
cb5c74e285
commit
d024bc60c4
|
@ -22,6 +22,7 @@ from oslo_service import service
|
||||||
from magnum.common import rpc
|
from magnum.common import rpc
|
||||||
from magnum.objects import base as objects_base
|
from magnum.objects import base as objects_base
|
||||||
from magnum.service import periodic
|
from magnum.service import periodic
|
||||||
|
from magnum.servicegroup import magnum_service_periodic as servicegroup
|
||||||
|
|
||||||
|
|
||||||
# NOTE(paulczar):
|
# NOTE(paulczar):
|
||||||
|
@ -69,8 +70,10 @@ class Service(service.Service):
|
||||||
self.binary = binary
|
self.binary = binary
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
|
# NOTE(suro-patz): The parent class has created a threadgroup, already
|
||||||
if CONF.periodic_enable:
|
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()
|
self._server.start()
|
||||||
|
|
||||||
def wait(self):
|
def wait(self):
|
||||||
|
|
|
@ -18,7 +18,6 @@ import six
|
||||||
|
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
from oslo_service import periodic_task
|
from oslo_service import periodic_task
|
||||||
from oslo_service import threadgroup
|
|
||||||
|
|
||||||
from magnum.common import clients
|
from magnum.common import clients
|
||||||
from magnum.common import context
|
from magnum.common import context
|
||||||
|
@ -61,33 +60,10 @@ class MagnumPeriodicTasks(periodic_task.PeriodicTasks):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, conf, binary):
|
def __init__(self, conf):
|
||||||
self.magnum_service_ref = None
|
|
||||||
self.host = conf.host
|
|
||||||
self.binary = binary
|
|
||||||
super(MagnumPeriodicTasks, self).__init__(conf)
|
super(MagnumPeriodicTasks, self).__init__(conf)
|
||||||
self.notifier = rpc.get_notifier()
|
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)
|
@periodic_task.periodic_task(run_immediately=True)
|
||||||
@set_context
|
@set_context
|
||||||
def sync_bay_status(self, ctx):
|
def sync_bay_status(self, ctx):
|
||||||
|
@ -210,11 +186,9 @@ class MagnumPeriodicTasks(periodic_task.PeriodicTasks):
|
||||||
message)
|
message)
|
||||||
|
|
||||||
|
|
||||||
def setup(conf, binary):
|
def setup(conf, tg):
|
||||||
tg = threadgroup.ThreadGroup()
|
pt = MagnumPeriodicTasks(conf)
|
||||||
pt = MagnumPeriodicTasks(conf, binary)
|
|
||||||
tg.add_dynamic_timer(
|
tg.add_dynamic_timer(
|
||||||
pt.run_periodic_tasks,
|
pt.run_periodic_tasks,
|
||||||
periodic_interval_max=conf.periodic_interval_max,
|
periodic_interval_max=conf.periodic_interval_max,
|
||||||
context=None)
|
context=None)
|
||||||
return tg
|
|
||||||
|
|
|
@ -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)
|
|
@ -51,14 +51,6 @@ class PeriodicTestCase(base.TestCase):
|
||||||
self.bay3 = objects.Bay(ctx, **bay3)
|
self.bay3 = objects.Bay(ctx, **bay3)
|
||||||
self.bay4 = objects.Bay(ctx, **bay4)
|
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.object(objects.Bay, 'list')
|
||||||
@mock.patch('magnum.common.clients.OpenStackClients')
|
@mock.patch('magnum.common.clients.OpenStackClients')
|
||||||
@mock.patch.object(dbapi.Connection, 'destroy_bay')
|
@mock.patch.object(dbapi.Connection, 'destroy_bay')
|
||||||
|
@ -79,8 +71,7 @@ class PeriodicTestCase(base.TestCase):
|
||||||
mock_keystone_client.client.project_id = "fake_project"
|
mock_keystone_client.client.project_id = "fake_project"
|
||||||
mock_osc.keystone.return_value = mock_keystone_client
|
mock_osc.keystone.return_value = mock_keystone_client
|
||||||
|
|
||||||
periodic.MagnumPeriodicTasks(CONF,
|
periodic.MagnumPeriodicTasks(CONF).sync_bay_status(None)
|
||||||
'fake-conductor').sync_bay_status(None)
|
|
||||||
|
|
||||||
self.assertEqual(bay_status.CREATE_COMPLETE, self.bay1.status)
|
self.assertEqual(bay_status.CREATE_COMPLETE, self.bay1.status)
|
||||||
self.assertEqual('fake_reason_11', self.bay1.status_reason)
|
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 = mock_oscc.return_value
|
||||||
mock_osc.heat.return_value = mock_heat_client
|
mock_osc.heat.return_value = mock_heat_client
|
||||||
mock_bay_list.return_value = [self.bay1, self.bay2, self.bay3]
|
mock_bay_list.return_value = [self.bay1, self.bay2, self.bay3]
|
||||||
periodic.MagnumPeriodicTasks(CONF,
|
periodic.MagnumPeriodicTasks(CONF).sync_bay_status(None)
|
||||||
'fake-conductor').sync_bay_status(None)
|
|
||||||
|
|
||||||
self.assertEqual(bay_status.CREATE_IN_PROGRESS, self.bay1.status)
|
self.assertEqual(bay_status.CREATE_IN_PROGRESS, self.bay1.status)
|
||||||
self.assertEqual(bay_status.DELETE_IN_PROGRESS, self.bay2.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_keystone_client.client.project_id = "fake_project"
|
||||||
mock_osc.keystone.return_value = mock_keystone_client
|
mock_osc.keystone.return_value = mock_keystone_client
|
||||||
|
|
||||||
periodic.MagnumPeriodicTasks(CONF,
|
periodic.MagnumPeriodicTasks(CONF).sync_bay_status(None)
|
||||||
'fake-conductor').sync_bay_status(None)
|
|
||||||
|
|
||||||
self.assertEqual(bay_status.CREATE_FAILED, self.bay1.status)
|
self.assertEqual(bay_status.CREATE_FAILED, self.bay1.status)
|
||||||
self.assertEqual('Stack with id 11 not found in Heat.',
|
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.assertEqual('Stack with id 33 not found in Heat.',
|
||||||
self.bay3.status_reason)
|
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.conductor.monitors.create_monitor')
|
||||||
@mock.patch('magnum.objects.Bay.list')
|
@mock.patch('magnum.objects.Bay.list')
|
||||||
@mock.patch('magnum.common.rpc.get_notifier')
|
@mock.patch('magnum.common.rpc.get_notifier')
|
||||||
|
@ -195,8 +144,7 @@ class PeriodicTestCase(base.TestCase):
|
||||||
monitor.get_metric_unit.return_value = '%'
|
monitor.get_metric_unit.return_value = '%'
|
||||||
mock_create_monitor.return_value = monitor
|
mock_create_monitor.return_value = monitor
|
||||||
|
|
||||||
periodic.MagnumPeriodicTasks(
|
periodic.MagnumPeriodicTasks(CONF)._send_bay_metrics(self.context)
|
||||||
CONF, 'fake-conductor')._send_bay_metrics(self.context)
|
|
||||||
|
|
||||||
expected_event_type = 'magnum.bay.metrics.update'
|
expected_event_type = 'magnum.bay.metrics.update'
|
||||||
expected_metrics = [
|
expected_metrics = [
|
||||||
|
@ -239,8 +187,7 @@ class PeriodicTestCase(base.TestCase):
|
||||||
"error on computing metric")
|
"error on computing metric")
|
||||||
mock_create_monitor.return_value = monitor
|
mock_create_monitor.return_value = monitor
|
||||||
|
|
||||||
periodic.MagnumPeriodicTasks(
|
periodic.MagnumPeriodicTasks(CONF)._send_bay_metrics(self.context)
|
||||||
CONF, 'fake-conductor')._send_bay_metrics(self.context)
|
|
||||||
|
|
||||||
expected_event_type = 'magnum.bay.metrics.update'
|
expected_event_type = 'magnum.bay.metrics.update'
|
||||||
expected_msg = {
|
expected_msg = {
|
||||||
|
@ -268,8 +215,7 @@ class PeriodicTestCase(base.TestCase):
|
||||||
monitor.pull_data.side_effect = Exception("error on pulling data")
|
monitor.pull_data.side_effect = Exception("error on pulling data")
|
||||||
mock_create_monitor.return_value = monitor
|
mock_create_monitor.return_value = monitor
|
||||||
|
|
||||||
periodic.MagnumPeriodicTasks(
|
periodic.MagnumPeriodicTasks(CONF)._send_bay_metrics(self.context)
|
||||||
CONF, 'fake-conductor')._send_bay_metrics(self.context)
|
|
||||||
|
|
||||||
self.assertEqual(1, mock_create_monitor.call_count)
|
self.assertEqual(1, mock_create_monitor.call_count)
|
||||||
self.assertEqual(0, notifier.info.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_bay_list.return_value = [self.bay4]
|
||||||
mock_create_monitor.return_value = None
|
mock_create_monitor.return_value = None
|
||||||
|
|
||||||
periodic.MagnumPeriodicTasks(
|
periodic.MagnumPeriodicTasks(CONF)._send_bay_metrics(self.context)
|
||||||
CONF, 'fake-conductor')._send_bay_metrics(self.context)
|
|
||||||
|
|
||||||
self.assertEqual(1, mock_create_monitor.call_count)
|
self.assertEqual(1, mock_create_monitor.call_count)
|
||||||
self.assertEqual(0, notifier.info.call_count)
|
self.assertEqual(0, notifier.info.call_count)
|
||||||
|
|
|
@ -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…
Reference in New Issue