Convert service and servicegroup to objects
This converts service and servicegroup to use objects instead of proxying through conductor. Adds missing object registration to cert and console scripts. Related to blueprint liberty-objects Change-Id: I87b077699c2ecbc25a83e5844e8c69fe147cec01
This commit is contained in:
parent
232c7afcf6
commit
19455514d1
|
@ -20,6 +20,7 @@ from oslo_config import cfg
|
|||
from oslo_log import log as logging
|
||||
|
||||
from nova import config
|
||||
from nova import objects
|
||||
from nova.openstack.common.report import guru_meditation_report as gmr
|
||||
from nova import service
|
||||
from nova import utils
|
||||
|
@ -33,6 +34,7 @@ def main():
|
|||
config.parse_args(sys.argv)
|
||||
logging.setup(CONF, "nova")
|
||||
utils.monkey_patch()
|
||||
objects.register_all()
|
||||
|
||||
gmr.TextGuruMeditation.setup_autorun(version)
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ from oslo_config import cfg
|
|||
from oslo_log import log as logging
|
||||
|
||||
from nova import config
|
||||
from nova import objects
|
||||
from nova.openstack.common.report import guru_meditation_report as gmr
|
||||
from nova import service
|
||||
from nova import version
|
||||
|
@ -32,6 +33,7 @@ CONF.import_opt('console_topic', 'nova.console.rpcapi')
|
|||
def main():
|
||||
config.parse_args(sys.argv)
|
||||
logging.setup(CONF, "nova")
|
||||
objects.register_all()
|
||||
|
||||
gmr.TextGuruMeditation.setup_autorun(version)
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ from nova import context
|
|||
from nova import debugger
|
||||
from nova import exception
|
||||
from nova.i18n import _, _LE, _LI, _LW
|
||||
from nova import objects
|
||||
from nova.objects import base as objects_base
|
||||
from nova.openstack.common import service
|
||||
from nova import rpc
|
||||
|
@ -136,14 +137,7 @@ class Service(service.Service):
|
|||
self.binary = binary
|
||||
self.topic = topic
|
||||
self.manager_class_name = manager
|
||||
# NOTE(russellb) We want to make sure to create the servicegroup API
|
||||
# instance early, before creating other things such as the manager,
|
||||
# that will also create a servicegroup API instance. Internally, the
|
||||
# servicegroup only allocates a single instance of the driver API and
|
||||
# we want to make sure that our value of db_allowed is there when it
|
||||
# gets created. For that to happen, this has to be the first instance
|
||||
# of the servicegroup API.
|
||||
self.servicegroup_api = servicegroup.API(db_allowed=db_allowed)
|
||||
self.servicegroup_api = servicegroup.API()
|
||||
manager_class = importutils.import_class(self.manager_class_name)
|
||||
self.manager = manager_class(host=self.host, *args, **kwargs)
|
||||
self.rpcserver = None
|
||||
|
@ -164,21 +158,17 @@ class Service(service.Service):
|
|||
self.manager.init_host()
|
||||
self.model_disconnected = False
|
||||
ctxt = context.get_admin_context()
|
||||
try:
|
||||
self.service_ref = (
|
||||
self.conductor_api.service_get_by_host_and_binary(
|
||||
ctxt, self.host, self.binary))
|
||||
self.service_id = self.service_ref['id']
|
||||
except exception.NotFound:
|
||||
self.service_ref = objects.Service.get_by_host_and_binary(
|
||||
ctxt, self.host, self.binary)
|
||||
if not self.service_ref:
|
||||
try:
|
||||
self.service_ref = self._create_service_ref(ctxt)
|
||||
except (exception.ServiceTopicExists,
|
||||
exception.ServiceBinaryExists):
|
||||
# NOTE(danms): If we race to create a record with a sibling
|
||||
# worker, don't fail here.
|
||||
self.service_ref = (
|
||||
self.conductor_api.service_get_by_host_and_binary(
|
||||
ctxt, self.host, self.binary))
|
||||
self.service_ref = objects.Service.get_by_host_and_binary(
|
||||
ctxt, self.host, self.binary)
|
||||
|
||||
self.manager.pre_start_hook()
|
||||
|
||||
|
@ -219,14 +209,12 @@ class Service(service.Service):
|
|||
self.periodic_interval_max)
|
||||
|
||||
def _create_service_ref(self, context):
|
||||
svc_values = {
|
||||
'host': self.host,
|
||||
'binary': self.binary,
|
||||
'topic': self.topic,
|
||||
'report_count': 0,
|
||||
}
|
||||
service = self.conductor_api.service_create(context, svc_values)
|
||||
self.service_id = service['id']
|
||||
service = objects.Service(context)
|
||||
service.host = self.host
|
||||
service.binary = self.binary
|
||||
service.topic = self.topic
|
||||
service.report_count = 0
|
||||
service.create()
|
||||
return service
|
||||
|
||||
def __getattr__(self, key):
|
||||
|
@ -282,8 +270,7 @@ class Service(service.Service):
|
|||
"""Destroy the service object in the datastore."""
|
||||
self.stop()
|
||||
try:
|
||||
self.conductor_api.service_destroy(context.get_admin_context(),
|
||||
self.service_id)
|
||||
self.service_ref.destroy()
|
||||
except exception.NotFound:
|
||||
LOG.warning(_LW('Service killed that has no database entry'))
|
||||
|
||||
|
|
|
@ -18,9 +18,9 @@ from oslo_log import log as logging
|
|||
from oslo_utils import timeutils
|
||||
import six
|
||||
|
||||
from nova import conductor
|
||||
from nova import context
|
||||
from nova.i18n import _, _LE
|
||||
from nova import objects
|
||||
from nova.servicegroup import api
|
||||
from nova.servicegroup.drivers import base
|
||||
|
||||
|
@ -34,16 +34,6 @@ LOG = logging.getLogger(__name__)
|
|||
class DbDriver(base.Driver):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Creates an instance of the DB-based servicegroup driver.
|
||||
|
||||
Valid kwargs are:
|
||||
|
||||
db_allowed - Boolean. False if direct db access is not allowed and
|
||||
alternative data access (conductor) should be used
|
||||
instead.
|
||||
"""
|
||||
self.db_allowed = kwargs.get('db_allowed', True)
|
||||
self.conductor_api = conductor.API(use_local=self.db_allowed)
|
||||
self.service_down_time = CONF.service_down_time
|
||||
|
||||
def join(self, member, group, service=None):
|
||||
|
@ -94,22 +84,17 @@ class DbDriver(base.Driver):
|
|||
LOG.debug('DB_Driver: get_all members of the %s group', group_id)
|
||||
rs = []
|
||||
ctxt = context.get_admin_context()
|
||||
services = self.conductor_api.service_get_all_by_topic(ctxt, group_id)
|
||||
services = objects.ServiceList.get_by_topic(ctxt, group_id)
|
||||
for service in services:
|
||||
if self.is_up(service):
|
||||
rs.append(service['host'])
|
||||
rs.append(service.host)
|
||||
return rs
|
||||
|
||||
def _report_state(self, service):
|
||||
"""Update the state of this service in the datastore."""
|
||||
ctxt = context.get_admin_context()
|
||||
state_catalog = {}
|
||||
try:
|
||||
report_count = service.service_ref['report_count'] + 1
|
||||
state_catalog['report_count'] = report_count
|
||||
|
||||
service.service_ref = self.conductor_api.service_update(ctxt,
|
||||
service.service_ref, state_catalog)
|
||||
service.service_ref.report_count += 1
|
||||
service.service_ref.save()
|
||||
|
||||
# TODO(termie): make this pattern be more elegant.
|
||||
if getattr(service, 'model_disconnected', False):
|
||||
|
|
|
@ -21,9 +21,9 @@ from oslo_config import cfg
|
|||
from oslo_log import log as logging
|
||||
from oslo_utils import timeutils
|
||||
|
||||
from nova import conductor
|
||||
from nova import context
|
||||
from nova.i18n import _, _LE
|
||||
from nova import objects
|
||||
from nova.openstack.common import memorycache
|
||||
from nova.servicegroup import api
|
||||
from nova.servicegroup.drivers import base
|
||||
|
@ -42,8 +42,6 @@ class MemcachedDriver(base.Driver):
|
|||
if not CONF.memcached_servers:
|
||||
raise RuntimeError(_('memcached_servers not defined'))
|
||||
self.mc = memorycache.get_client()
|
||||
self.db_allowed = kwargs.get('db_allowed', True)
|
||||
self.conductor_api = conductor.API(use_local=self.db_allowed)
|
||||
|
||||
def join(self, member_id, group_id, service=None):
|
||||
"""Join the given service with its group."""
|
||||
|
@ -80,10 +78,10 @@ class MemcachedDriver(base.Driver):
|
|||
group_id)
|
||||
rs = []
|
||||
ctxt = context.get_admin_context()
|
||||
services = self.conductor_api.service_get_all_by_topic(ctxt, group_id)
|
||||
services = objects.ServiceList.get_by_topic(ctxt, group_id)
|
||||
for service in services:
|
||||
if self.is_up(service):
|
||||
rs.append(service['host'])
|
||||
rs.append(service.host)
|
||||
return rs
|
||||
|
||||
def _report_state(self, service):
|
||||
|
|
|
@ -2782,6 +2782,11 @@ class ServiceTestCase(test.TestCase, ModelsObjectComparatorMixin):
|
|||
for key, value in self._get_base_values().iteritems():
|
||||
self.assertEqual(value, service[key])
|
||||
|
||||
def test_service_create_disabled(self):
|
||||
self.flags(enable_new_services=False)
|
||||
service = self._create_service({})
|
||||
self.assertTrue(service['disabled'])
|
||||
|
||||
def test_service_destroy(self):
|
||||
service1 = self._create_service({})
|
||||
service2 = self._create_service({'host': 'fake_host2'})
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
import datetime
|
||||
import mock
|
||||
|
||||
from nova import objects
|
||||
from nova import servicegroup
|
||||
from nova import test
|
||||
|
||||
|
@ -57,22 +58,11 @@ class DBServiceGroupTestCase(test.NoDBTestCase):
|
|||
result = self.servicegroup_api.service_is_up(service_ref)
|
||||
self.assertFalse(result)
|
||||
|
||||
@mock.patch('nova.conductor.api.LocalAPI.service_get_all_by_topic')
|
||||
@mock.patch.object(objects.ServiceList, 'get_by_topic')
|
||||
def test_get_all(self, ga_mock):
|
||||
service_refs = [
|
||||
{
|
||||
'host': 'fake-host1',
|
||||
'topic': 'compute'
|
||||
},
|
||||
{
|
||||
'host': 'fake-host2',
|
||||
'topic': 'compute'
|
||||
},
|
||||
{
|
||||
'host': 'fake-host3',
|
||||
'topic': 'compute'
|
||||
},
|
||||
]
|
||||
hosts = ['fake-host1', 'fake-host2', 'fake-host3']
|
||||
service_refs = objects.ServiceList(objects=[
|
||||
objects.Service(host=host, topic='compute') for host in hosts])
|
||||
ga_mock.return_value = service_refs
|
||||
with mock.patch.object(self.servicegroup_api._driver,
|
||||
'is_up', side_effect=[
|
||||
|
@ -91,17 +81,13 @@ class DBServiceGroupTestCase(test.NoDBTestCase):
|
|||
fn = self.servicegroup_api._driver._report_state
|
||||
service.tg.add_timer.assert_called_once_with(1, fn, 5, service)
|
||||
|
||||
@mock.patch('nova.conductor.api.LocalAPI.service_update')
|
||||
@mock.patch.object(objects.Service, 'save')
|
||||
def test_report_state(self, upd_mock):
|
||||
service_ref = {
|
||||
'host': 'fake-host',
|
||||
'topic': 'compute',
|
||||
'report_count': 10
|
||||
}
|
||||
service_ref = objects.Service(host='fake-host', topic='compute',
|
||||
report_count=10)
|
||||
service = mock.MagicMock(model_disconnected=False,
|
||||
service_ref=service_ref)
|
||||
fn = self.servicegroup_api._driver._report_state
|
||||
fn(service)
|
||||
upd_mock.assert_called_once_with(mock.ANY,
|
||||
service_ref,
|
||||
dict(report_count=11))
|
||||
upd_mock.assert_called_once_with()
|
||||
self.assertEqual(11, service_ref.report_count)
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
import mock
|
||||
|
||||
from nova import objects
|
||||
from nova import servicegroup
|
||||
from nova import test
|
||||
|
||||
|
@ -46,22 +47,11 @@ class MemcachedServiceGroupTestCase(test.NoDBTestCase):
|
|||
self.assertTrue(self.servicegroup_api.service_is_up(service_ref))
|
||||
self.mc_client.get.assert_called_once_with('compute:fake-host')
|
||||
|
||||
@mock.patch('nova.conductor.api.LocalAPI.service_get_all_by_topic')
|
||||
@mock.patch.object(objects.ServiceList, 'get_by_topic')
|
||||
def test_get_all(self, ga_mock):
|
||||
service_refs = [
|
||||
{
|
||||
'host': 'fake-host1',
|
||||
'topic': 'compute'
|
||||
},
|
||||
{
|
||||
'host': 'fake-host2',
|
||||
'topic': 'compute'
|
||||
},
|
||||
{
|
||||
'host': 'fake-host3',
|
||||
'topic': 'compute'
|
||||
},
|
||||
]
|
||||
hosts = ['fake-host1', 'fake-host2', 'fake-host3']
|
||||
service_refs = objects.ServiceList(objects=[
|
||||
objects.Service(host=host, topic='compute') for host in hosts])
|
||||
ga_mock.return_value = service_refs
|
||||
self.mc_client.get.side_effect = [
|
||||
None,
|
||||
|
|
|
@ -26,10 +26,9 @@ from oslo_concurrency import processutils
|
|||
from oslo_config import cfg
|
||||
import testtools
|
||||
|
||||
from nova import context
|
||||
from nova import db
|
||||
from nova import exception
|
||||
from nova import manager
|
||||
from nova import objects
|
||||
from nova.openstack.common import service as _service
|
||||
from nova import rpc
|
||||
from nova import service
|
||||
|
@ -94,31 +93,7 @@ class ServiceManagerTestCase(test.TestCase):
|
|||
self.assertEqual(CONF.service_down_time, 25)
|
||||
|
||||
|
||||
class ServiceFlagsTestCase(test.TestCase):
|
||||
def test_service_enabled_on_create_based_on_flag(self):
|
||||
self.flags(enable_new_services=True)
|
||||
host = 'foo'
|
||||
binary = 'nova-fake'
|
||||
app = service.Service.create(host=host, binary=binary)
|
||||
app.start()
|
||||
app.stop()
|
||||
ref = db.service_get(context.get_admin_context(), app.service_id)
|
||||
db.service_destroy(context.get_admin_context(), app.service_id)
|
||||
self.assertFalse(ref['disabled'])
|
||||
|
||||
def test_service_disabled_on_create_based_on_flag(self):
|
||||
self.flags(enable_new_services=False)
|
||||
host = 'foo'
|
||||
binary = 'nova-fake'
|
||||
app = service.Service.create(host=host, binary=binary)
|
||||
app.start()
|
||||
app.stop()
|
||||
ref = db.service_get(context.get_admin_context(), app.service_id)
|
||||
db.service_destroy(context.get_admin_context(), app.service_id)
|
||||
self.assertTrue(ref['disabled'])
|
||||
|
||||
|
||||
class ServiceTestCase(test.TestCase):
|
||||
class ServiceTestCase(test.NoDBTestCase):
|
||||
"""Test cases for Services."""
|
||||
|
||||
def setUp(self):
|
||||
|
@ -126,8 +101,6 @@ class ServiceTestCase(test.TestCase):
|
|||
self.host = 'foo'
|
||||
self.binary = 'nova-fake'
|
||||
self.topic = 'fake'
|
||||
self.mox.StubOutWithMock(db, 'service_create')
|
||||
self.mox.StubOutWithMock(db, 'service_get_by_host_and_binary')
|
||||
self.flags(use_local=True, group='conductor')
|
||||
|
||||
def test_create(self):
|
||||
|
@ -140,21 +113,11 @@ class ServiceTestCase(test.TestCase):
|
|||
self.assertTrue(app)
|
||||
|
||||
def _service_start_mocks(self):
|
||||
service_create = {'host': self.host,
|
||||
'binary': self.binary,
|
||||
'topic': self.topic,
|
||||
'report_count': 0}
|
||||
service_ref = {'host': self.host,
|
||||
'binary': self.binary,
|
||||
'topic': self.topic,
|
||||
'report_count': 0,
|
||||
'id': 1}
|
||||
|
||||
db.service_get_by_host_and_binary(mox.IgnoreArg(),
|
||||
self.host, self.binary).AndRaise(exception.NotFound())
|
||||
db.service_create(mox.IgnoreArg(),
|
||||
service_create).AndReturn(service_ref)
|
||||
return service_ref
|
||||
self.mox.StubOutWithMock(objects.Service, 'create')
|
||||
self.mox.StubOutWithMock(objects.Service, 'get_by_host_and_binary')
|
||||
objects.Service.get_by_host_and_binary(mox.IgnoreArg(), self.host,
|
||||
self.binary)
|
||||
objects.Service.create()
|
||||
|
||||
def test_init_and_start_hooks(self):
|
||||
self.manager_mock = self.mox.CreateMock(FakeManager)
|
||||
|
@ -193,23 +156,23 @@ class ServiceTestCase(test.TestCase):
|
|||
self.mox.StubOutWithMock(self.manager_mock, 'init_host')
|
||||
self.mox.StubOutWithMock(self.manager_mock, 'pre_start_hook')
|
||||
self.mox.StubOutWithMock(self.manager_mock, 'post_start_hook')
|
||||
self.mox.StubOutWithMock(objects.Service, 'create')
|
||||
self.mox.StubOutWithMock(objects.Service, 'get_by_host_and_binary')
|
||||
|
||||
FakeManager(host=self.host).AndReturn(self.manager_mock)
|
||||
|
||||
# init_host is called before any service record is created
|
||||
self.manager_mock.init_host()
|
||||
|
||||
db.service_get_by_host_and_binary(
|
||||
mox.IgnoreArg(), self.host, self.binary).AndRaise(
|
||||
exception.NotFound)
|
||||
db.service_create(mox.IgnoreArg(), mox.IgnoreArg()
|
||||
).AndRaise(ex)
|
||||
objects.Service.get_by_host_and_binary(mox.IgnoreArg(), self.host,
|
||||
self.binary)
|
||||
objects.Service.create().AndRaise(ex)
|
||||
|
||||
class TestException(Exception):
|
||||
pass
|
||||
|
||||
db.service_get_by_host_and_binary(
|
||||
mox.IgnoreArg(), self.host, self.binary).AndRaise(TestException)
|
||||
objects.Service.get_by_host_and_binary(
|
||||
mox.IgnoreArg(), self.host, self.binary).AndRaise(TestException())
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
|
@ -264,10 +227,9 @@ class ServiceTestCase(test.TestCase):
|
|||
serv.stop()
|
||||
|
||||
@mock.patch('nova.servicegroup.API')
|
||||
@mock.patch('nova.conductor.api.LocalAPI.service_get_by_host_and_binary')
|
||||
@mock.patch('nova.objects.service.Service.get_by_host_and_binary')
|
||||
def test_parent_graceful_shutdown_with_cleanup_host(
|
||||
self, mock_svc_get_by_host_and_binary, mock_API):
|
||||
mock_svc_get_by_host_and_binary.return_value = {'id': 'some_value'}
|
||||
mock_manager = mock.Mock()
|
||||
|
||||
serv = service.Service(self.host,
|
||||
|
@ -285,11 +247,10 @@ class ServiceTestCase(test.TestCase):
|
|||
serv.manager.cleanup_host.assert_called_with()
|
||||
|
||||
@mock.patch('nova.servicegroup.API')
|
||||
@mock.patch('nova.conductor.api.LocalAPI.service_get_by_host_and_binary')
|
||||
@mock.patch('nova.objects.service.Service.get_by_host_and_binary')
|
||||
@mock.patch.object(rpc, 'get_server')
|
||||
def test_service_stop_waits_for_rpcserver(
|
||||
self, mock_rpc, mock_svc_get_by_host_and_binary, mock_API):
|
||||
mock_svc_get_by_host_and_binary.return_value = {'id': 'some_value'}
|
||||
serv = service.Service(self.host,
|
||||
self.binary,
|
||||
self.topic,
|
||||
|
|
Loading…
Reference in New Issue