Remove conductor local api:s and 'use_local' config option

This change removes the deprecated conductor local mode and the
'use_local' flag that was used to control it.

UpgradeImpact

Change-Id: Icc1624606ecb561781a971467443e24b1643f535
changes/96/387996/1
Hans Lindgren 6 years ago
parent 0360e4c93d
commit c36dbe1f72
  1. 4
      nova/cmd/api_metadata.py
  2. 13
      nova/cmd/compute.py
  3. 11
      nova/cmd/dhcpbridge.py
  4. 12
      nova/cmd/network.py
  5. 21
      nova/conductor/__init__.py
  6. 106
      nova/conductor/api.py
  7. 12
      nova/conf/conductor.py
  8. 14
      nova/service.py
  9. 107
      nova/tests/unit/conductor/test_conductor.py
  10. 9
      releasenotes/notes/rm-conductor-local-apis-f121afaee99f6fa4.yaml

@ -42,9 +42,7 @@ def main():
gmr.TextGuruMeditation.setup_autorun(version)
if not CONF.conductor.use_local:
objects_base.NovaObject.indirection_api = \
conductor_rpcapi.ConductorAPI()
objects_base.NovaObject.indirection_api = conductor_rpcapi.ConductorAPI()
should_use_ssl = 'metadata' in CONF.enabled_ssl_apis
server = service.WSGIService('metadata', use_ssl=should_use_ssl)

@ -28,7 +28,6 @@ from nova.cmd import common as cmd_common
from nova.conductor import rpcapi as conductor_rpcapi
import nova.conf
from nova import config
from nova.i18n import _LW
from nova import objects
from nova.objects import base as objects_base
from nova import service
@ -50,16 +49,10 @@ def main():
gmr.TextGuruMeditation.setup_autorun(version)
if not CONF.conductor.use_local:
cmd_common.block_db_access('nova-compute')
objects_base.NovaObject.indirection_api = \
conductor_rpcapi.ConductorAPI()
else:
LOG.warning(_LW('Conductor local mode is deprecated and will '
'be removed in a subsequent release'))
cmd_common.block_db_access('nova-compute')
objects_base.NovaObject.indirection_api = conductor_rpcapi.ConductorAPI()
server = service.Service.create(binary='nova-compute',
topic=CONF.compute_topic,
db_allowed=CONF.conductor.use_local)
topic=CONF.compute_topic)
service.serve(server)
service.wait()

@ -33,7 +33,7 @@ from nova.conductor import rpcapi as conductor_rpcapi
import nova.conf
from nova import config
from nova import context
from nova.i18n import _LE, _LW
from nova.i18n import _LE
from nova.network import rpcapi as network_rpcapi
from nova import objects
from nova.objects import base as objects_base
@ -117,13 +117,8 @@ def main():
objects.register_all()
if not CONF.conductor.use_local:
cmd_common.block_db_access('nova-dhcpbridge')
objects_base.NovaObject.indirection_api = \
conductor_rpcapi.ConductorAPI()
else:
LOG.warning(_LW('Conductor local mode is deprecated and will '
'be removed in a subsequent release'))
cmd_common.block_db_access('nova-dhcpbridge')
objects_base.NovaObject.indirection_api = conductor_rpcapi.ConductorAPI()
if CONF.action.name in ['add', 'del']:
LOG.debug("Called '%(action)s' for mac '%(mac)s' with IP '%(ip)s'",

@ -44,18 +44,12 @@ def main():
gmr.TextGuruMeditation.setup_autorun(version)
if not CONF.conductor.use_local:
cmd_common.block_db_access('nova-network')
objects_base.NovaObject.indirection_api = \
conductor_rpcapi.ConductorAPI()
else:
LOG.warning(_LW('Conductor local mode is deprecated and will '
'be removed in a subsequent release'))
cmd_common.block_db_access('nova-network')
objects_base.NovaObject.indirection_api = conductor_rpcapi.ConductorAPI()
LOG.warning(_LW('Nova network is deprecated and will be removed '
'in the future'))
server = service.Service.create(binary='nova-network',
topic=CONF.network_topic,
db_allowed=CONF.conductor.use_local)
topic=CONF.network_topic)
service.serve(server)
service.wait()

@ -14,24 +14,7 @@
from nova.conductor import api as conductor_api
import nova.conf
CONF = nova.conf.CONF
def API(*args, **kwargs):
use_local = kwargs.pop('use_local', False)
if CONF.conductor.use_local or use_local:
api = conductor_api.LocalAPI
else:
api = conductor_api.API
return api(*args, **kwargs)
def ComputeTaskAPI(*args, **kwargs):
use_local = kwargs.pop('use_local', False)
if CONF.conductor.use_local or use_local:
api = conductor_api.LocalComputeTaskAPI
else:
api = conductor_api.ComputeTaskAPI
return api(*args, **kwargs)
API = conductor_api.API
ComputeTaskAPI = conductor_api.ComputeTaskAPI

@ -16,122 +16,28 @@
from oslo_log import log as logging
import oslo_messaging as messaging
from oslo_versionedobjects import base as ovo_base
from nova import baserpc
from nova.conductor import manager
from nova.conductor import rpcapi
import nova.conf
from nova.i18n import _LI, _LW
from nova import utils
CONF = nova.conf.CONF
LOG = logging.getLogger(__name__)
class LocalAPI(object):
"""A local version of the conductor API that does database updates
locally instead of via RPC.
"""
def __init__(self):
# TODO(danms): This needs to be something more generic for
# other/future users of this sort of functionality.
self._manager = utils.ExceptionHelper(manager.ConductorManager())
def wait_until_ready(self, context, *args, **kwargs):
# nothing to wait for in the local case.
pass
def object_backport(self, context, objinst, target_version):
# NOTE(hanlind): This shouldn't be called anymore but leaving it for
# now just in case. Collect the object version manifest and redirect
# to the newer backport call.
object_versions = ovo_base.obj_tree_get_versions(objinst.obj_name())
return self.object_backport_versions(context, objinst, object_versions)
def object_backport_versions(self, context, objinst, object_versions):
return self._manager.object_backport_versions(context, objinst,
object_versions)
class LocalComputeTaskAPI(object):
def __init__(self):
# TODO(danms): This needs to be something more generic for
# other/future users of this sort of functionality.
self._manager = utils.ExceptionHelper(
manager.ComputeTaskManager())
def resize_instance(self, context, instance, extra_instance_updates,
scheduler_hint, flavor, reservations,
clean_shutdown=True, request_spec=None):
# NOTE(comstud): 'extra_instance_updates' is not used here but is
# needed for compatibility with the cells_rpcapi version of this
# method.
self._manager.migrate_server(
context, instance, scheduler_hint, live=False, rebuild=False,
flavor=flavor, block_migration=None, disk_over_commit=None,
reservations=reservations, clean_shutdown=clean_shutdown,
request_spec=request_spec)
def live_migrate_instance(self, context, instance, host_name,
block_migration, disk_over_commit,
request_spec=None, async=False):
scheduler_hint = {'host': host_name}
if async:
wrap = lambda *args: utils.spawn_n(*args)
else:
wrap = lambda *args: args[0](*args[1:])
wrap(self._manager.live_migrate_instance, context, instance,
scheduler_hint, block_migration, disk_over_commit, request_spec)
def build_instances(self, context, instances, image,
filter_properties, admin_password, injected_files,
requested_networks, security_groups, block_device_mapping,
legacy_bdm=True):
utils.spawn_n(self._manager.build_instances, context,
instances=instances, image=image,
filter_properties=filter_properties,
admin_password=admin_password, injected_files=injected_files,
requested_networks=requested_networks,
security_groups=security_groups,
block_device_mapping=block_device_mapping,
legacy_bdm=legacy_bdm)
def unshelve_instance(self, context, instance, request_spec=None):
utils.spawn_n(self._manager.unshelve_instance, context,
instance=instance, request_spec=request_spec)
def rebuild_instance(self, context, instance, orig_image_ref, image_ref,
injected_files, new_pass, orig_sys_metadata,
bdms, recreate=False, on_shared_storage=False,
preserve_ephemeral=False, host=None,
request_spec=None, kwargs=None):
# kwargs unused but required for cell compatibility.
utils.spawn_n(self._manager.rebuild_instance, context,
instance=instance,
new_pass=new_pass,
injected_files=injected_files,
image_ref=image_ref,
orig_image_ref=orig_image_ref,
orig_sys_metadata=orig_sys_metadata,
bdms=bdms,
recreate=recreate,
on_shared_storage=on_shared_storage,
host=host,
preserve_ephemeral=preserve_ephemeral,
request_spec=request_spec)
class API(LocalAPI):
class API(object):
"""Conductor API that does updates via RPC to the ConductorManager."""
def __init__(self):
self._manager = rpcapi.ConductorAPI()
self.conductor_rpcapi = rpcapi.ConductorAPI()
self.base_rpcapi = baserpc.BaseAPI(topic=CONF.conductor.topic)
def object_backport_versions(self, context, objinst, object_versions):
return self.conductor_rpcapi.object_backport_versions(context, objinst,
object_versions)
def wait_until_ready(self, context, early_timeout=10, early_attempts=10):
'''Wait until a conductor service is up and running.

@ -26,18 +26,6 @@ and finally, how many worker processes will be used.
)
ALL_OPTS = [
cfg.BoolOpt(
'use_local',
default=False,
deprecated_for_removal=True,
deprecated_since='13.0.0',
help="""
Perform nova-conductor operations locally. This legacy mode was
introduced to bridge a gap during the transition to the conductor service.
It no longer represents a reasonable alternative for deployers.
Removal may be as early as 14.0.
"""),
cfg.StrOpt(
'topic',
default='conductor',

@ -80,8 +80,7 @@ class Service(service.Service):
def __init__(self, host, binary, topic, manager, report_interval=None,
periodic_enable=None, periodic_fuzzy_delay=None,
periodic_interval_max=None, db_allowed=True,
*args, **kwargs):
periodic_interval_max=None, *args, **kwargs):
super(Service, self).__init__()
self.host = host
self.binary = binary
@ -97,8 +96,9 @@ class Service(service.Service):
self.periodic_interval_max = periodic_interval_max
self.saved_args, self.saved_kwargs = args, kwargs
self.backdoor_port = None
self.conductor_api = conductor.API(use_local=db_allowed)
self.conductor_api.wait_until_ready(context.get_admin_context())
if objects_base.NovaObject.indirection_api:
conductor_api = conductor.API()
conductor_api.wait_until_ready(context.get_admin_context())
def __repr__(self):
return "<%(cls_name)s: host=%(host)s, binary=%(binary)s, " \
@ -177,8 +177,7 @@ class Service(service.Service):
@classmethod
def create(cls, host=None, binary=None, topic=None, manager=None,
report_interval=None, periodic_enable=None,
periodic_fuzzy_delay=None, periodic_interval_max=None,
db_allowed=True):
periodic_fuzzy_delay=None, periodic_interval_max=None):
"""Instantiates class and passes back application object.
:param host: defaults to CONF.host
@ -214,8 +213,7 @@ class Service(service.Service):
report_interval=report_interval,
periodic_enable=periodic_enable,
periodic_fuzzy_delay=periodic_fuzzy_delay,
periodic_interval_max=periodic_interval_max,
db_allowed=db_allowed)
periodic_interval_max=periodic_interval_max)
return service_obj

@ -28,7 +28,6 @@ from nova.compute import flavors
from nova.compute import rpcapi as compute_rpcapi
from nova.compute import task_states
from nova.compute import vm_states
from nova import conductor
from nova.conductor import api as conductor_api
from nova.conductor import manager as conductor_manager
from nova.conductor import rpcapi as conductor_rpcapi
@ -279,53 +278,6 @@ class ConductorAPITestCase(_BaseTestCase, test.TestCase):
self.assertEqual(timeouts.count(10), 10)
self.assertIn(None, timeouts)
@mock.patch('oslo_versionedobjects.base.obj_tree_get_versions')
def test_object_backport_redirect(self, mock_ovo):
mock_ovo.return_value = mock.sentinel.obj_versions
mock_objinst = mock.Mock()
with mock.patch.object(self.conductor,
'object_backport_versions') as mock_call:
self.conductor.object_backport(mock.sentinel.ctxt,
mock_objinst,
mock.sentinel.target_version)
mock_call.assert_called_once_with(mock.sentinel.ctxt,
mock_objinst,
mock.sentinel.obj_versions)
class ConductorLocalAPITestCase(ConductorAPITestCase):
"""Conductor LocalAPI Tests."""
def setUp(self):
super(ConductorLocalAPITestCase, self).setUp()
self.conductor = conductor_api.LocalAPI()
self.conductor_manager = self.conductor._manager._target
def test_wait_until_ready(self):
# Override test in ConductorAPITestCase
pass
class ConductorImportTest(test.NoDBTestCase):
def test_import_conductor_local(self):
self.flags(use_local=True, group='conductor')
self.assertIsInstance(conductor.API(), conductor_api.LocalAPI)
self.assertIsInstance(conductor.ComputeTaskAPI(),
conductor_api.LocalComputeTaskAPI)
def test_import_conductor_rpc(self):
self.flags(use_local=False, group='conductor')
self.assertIsInstance(conductor.API(), conductor_api.API)
self.assertIsInstance(conductor.ComputeTaskAPI(),
conductor_api.ComputeTaskAPI)
def test_import_conductor_override_to_local(self):
self.flags(use_local=False, group='conductor')
self.assertIsInstance(conductor.API(use_local=True),
conductor_api.LocalAPI)
self.assertIsInstance(conductor.ComputeTaskAPI(use_local=True),
conductor_api.LocalComputeTaskAPI)
class _BaseTaskTestCase(object):
def setUp(self):
@ -395,8 +347,7 @@ class _BaseTaskTestCase(object):
scheduler_hint = {'filter_properties': {}}
if isinstance(self.conductor, (conductor_api.ComputeTaskAPI,
conductor_api.LocalComputeTaskAPI)):
if isinstance(self.conductor, conductor_api.ComputeTaskAPI):
# The API method is actually 'resize_instance'. It gets
# converted into 'migrate_server' when doing RPC.
self.conductor.resize_instance(
@ -2111,59 +2062,3 @@ class ConductorTaskAPITestCase(_BaseTaskTestCase, test_compute.BaseTestCase):
self.context, inst_obj, {'host': 'destination'}, True, False,
None, 'block_migration', 'disk_over_commit', None,
request_spec=None)
class ConductorLocalComputeTaskAPITestCase(ConductorTaskAPITestCase):
"""Conductor LocalComputeTaskAPI Tests."""
def setUp(self):
super(ConductorLocalComputeTaskAPITestCase, self).setUp()
self.conductor = conductor_api.LocalComputeTaskAPI()
self.conductor_manager = self.conductor._manager._target
@mock.patch('nova.objects.Migration')
def test_live_migrate(self, migobj):
inst = fake_instance.fake_db_instance()
inst_obj = objects.Instance._from_db_object(
self.context, objects.Instance(), inst, [])
migration = migobj()
task = mock.MagicMock()
with mock.patch.object(self.conductor_manager,
'_build_live_migrate_task',
return_value=task) as mock_build_task:
self.conductor.live_migrate_instance(self.context, inst_obj,
'destination', 'block_migration', 'disk_over_commit',
async=False)
mock_build_task.assert_called_once_with(self.context, inst_obj,
'destination',
'block_migration',
'disk_over_commit',
migration, None)
task.execute.assert_called_once()
self.assertEqual('accepted', migration.status)
self.assertEqual('destination', migration.dest_compute)
self.assertEqual(inst_obj.host, migration.source_compute)
@mock.patch('nova.objects.Migration')
def test_live_migrate_async(self, migobj):
inst = fake_instance.fake_db_instance()
inst_obj = objects.Instance._from_db_object(
self.context, objects.Instance(), inst, [])
migration = migobj()
task = mock.MagicMock()
with mock.patch.object(self.conductor_manager,
'_build_live_migrate_task',
return_value=task) as mock_build_task:
self.conductor.live_migrate_instance(self.context, inst_obj,
'destination', 'block_migration', 'disk_over_commit',
async=True)
mock_build_task.assert_called_once_with(self.context, inst_obj,
'destination',
'block_migration',
'disk_over_commit',
migration, None)
task.execute.assert_called_once()
self.assertEqual('accepted', migration.status)
self.assertEqual('destination', migration.dest_compute)
self.assertEqual(inst_obj.host, migration.source_compute)

@ -0,0 +1,9 @@
---
upgrade:
- |
The ''use_local'' option, which made it possible to
perform nova-conductor operations locally, has been
removed. This legacy mode was introduced to bridge a
gap during the transition to the conductor service.
It no longer represents a reasonable alternative for
deployers.
Loading…
Cancel
Save