Remove deprecated monkey_patch config options

These were deprecated in Queens:

  Id793ac2c5cdc5dc473f95eac53b77617a1e389da

And can now be removed.

Change-Id: I27518d1154ec09c57700905bc58ae6a3ce1d8049
This commit is contained in:
Matt Riedemann 2018-05-16 11:28:41 -04:00
parent 3693caa541
commit 9f48aee9b0
22 changed files with 15 additions and 354 deletions

View File

@ -23,13 +23,11 @@ from nova import context
from nova import exception from nova import exception
from nova import objects from nova import objects
from nova import service from nova import service
from nova import utils
CONF = cfg.CONF CONF = cfg.CONF
CONFIG_FILES = ['api-paste.ini', 'nova.conf'] CONFIG_FILES = ['api-paste.ini', 'nova.conf']
utils.monkey_patch()
objects.register_all() objects.register_all()

View File

@ -31,7 +31,6 @@ from nova import config
from nova import exception from nova import exception
from nova import objects from nova import objects
from nova import service from nova import service
from nova import utils
from nova import version from nova import version
CONF = nova.conf.CONF CONF = nova.conf.CONF
@ -40,7 +39,6 @@ CONF = nova.conf.CONF
def main(): def main():
config.parse_args(sys.argv) config.parse_args(sys.argv)
logging.setup(CONF, "nova") logging.setup(CONF, "nova")
utils.monkey_patch()
objects.register_all() objects.register_all()
gmr_opts.set_defaults(CONF) gmr_opts.set_defaults(CONF)
if 'osapi_compute' in CONF.enabled_apis: if 'osapi_compute' in CONF.enabled_apis:

View File

@ -28,7 +28,6 @@ from nova import config
from nova import objects from nova import objects
from nova.objects import base as objects_base from nova.objects import base as objects_base
from nova import service from nova import service
from nova import utils
from nova import version from nova import version
@ -38,7 +37,6 @@ CONF = nova.conf.CONF
def main(): def main():
config.parse_args(sys.argv) config.parse_args(sys.argv)
logging.setup(CONF, "nova") logging.setup(CONF, "nova")
utils.monkey_patch()
objects.register_all() objects.register_all()
gmr_opts.set_defaults(CONF) gmr_opts.set_defaults(CONF)

View File

@ -26,7 +26,6 @@ import nova.conf
from nova import config from nova import config
from nova import objects from nova import objects
from nova import service from nova import service
from nova import utils
from nova import version from nova import version
@ -36,7 +35,6 @@ CONF = nova.conf.CONF
def main(): def main():
config.parse_args(sys.argv) config.parse_args(sys.argv)
logging.setup(CONF, "nova") logging.setup(CONF, "nova")
utils.monkey_patch()
objects.register_all() objects.register_all()
gmr_opts.set_defaults(CONF) gmr_opts.set_defaults(CONF)
# NOTE(mriedem): This is needed for caching the nova-compute service # NOTE(mriedem): This is needed for caching the nova-compute service

View File

@ -26,7 +26,6 @@ import nova.conf
from nova import config from nova import config
from nova import objects from nova import objects
from nova import service from nova import service
from nova import utils
from nova import version from nova import version
CONF = nova.conf.CONF CONF = nova.conf.CONF
@ -36,7 +35,6 @@ LOG = logging.getLogger('nova.cells')
def main(): def main():
config.parse_args(sys.argv) config.parse_args(sys.argv)
logging.setup(CONF, 'nova') logging.setup(CONF, 'nova')
utils.monkey_patch()
objects.register_all() objects.register_all()
gmr_opts.set_defaults(CONF) gmr_opts.set_defaults(CONF)

View File

@ -43,7 +43,6 @@ def main():
config.parse_args(sys.argv) config.parse_args(sys.argv)
logging.setup(CONF, 'nova') logging.setup(CONF, 'nova')
priv_context.init(root_helper=shlex.split(utils.get_root_helper())) priv_context.init(root_helper=shlex.split(utils.get_root_helper()))
utils.monkey_patch()
objects.register_all() objects.register_all()
gmr_opts.set_defaults(CONF) gmr_opts.set_defaults(CONF)
# Ensure os-vif objects are registered and plugins loaded # Ensure os-vif objects are registered and plugins loaded

View File

@ -26,7 +26,6 @@ import nova.conf
from nova import config from nova import config
from nova import objects from nova import objects
from nova import service from nova import service
from nova import utils
from nova import version from nova import version
CONF = nova.conf.CONF CONF = nova.conf.CONF
@ -35,7 +34,6 @@ CONF = nova.conf.CONF
def main(): def main():
config.parse_args(sys.argv) config.parse_args(sys.argv)
logging.setup(CONF, "nova") logging.setup(CONF, "nova")
utils.monkey_patch()
objects.register_all() objects.register_all()
gmr_opts.set_defaults(CONF) gmr_opts.set_defaults(CONF)
objects.Service.enable_min_version_cache() objects.Service.enable_min_version_cache()

View File

@ -30,7 +30,6 @@ from nova.network import rpcapi as network_rpcapi
from nova import objects from nova import objects
from nova.objects import base as objects_base from nova.objects import base as objects_base
from nova import service from nova import service
from nova import utils
from nova import version from nova import version
CONF = nova.conf.CONF CONF = nova.conf.CONF
@ -46,7 +45,6 @@ def main():
'except as required for CellsV1 deployments.') 'except as required for CellsV1 deployments.')
return 1 return 1
utils.monkey_patch()
objects.register_all() objects.register_all()
gmr_opts.set_defaults(CONF) gmr_opts.set_defaults(CONF)

View File

@ -28,7 +28,6 @@ from nova import config
from nova import objects from nova import objects
from nova.scheduler import rpcapi as scheduler_rpcapi from nova.scheduler import rpcapi as scheduler_rpcapi
from nova import service from nova import service
from nova import utils
from nova import version from nova import version
CONF = nova.conf.CONF CONF = nova.conf.CONF
@ -37,7 +36,6 @@ CONF = nova.conf.CONF
def main(): def main():
config.parse_args(sys.argv) config.parse_args(sys.argv)
logging.setup(CONF, "nova") logging.setup(CONF, "nova")
utils.monkey_patch()
objects.register_all() objects.register_all()
gmr_opts.set_defaults(CONF) gmr_opts.set_defaults(CONF)
objects.Service.enable_min_version_cache() objects.Service.enable_min_version_cache()

View File

@ -60,48 +60,6 @@ entry.
cfg.StrOpt( cfg.StrOpt(
'tempdir', 'tempdir',
help='Explicitly specify the temporary working directory.'), help='Explicitly specify the temporary working directory.'),
cfg.BoolOpt(
'monkey_patch',
default=False,
deprecated_for_removal=True,
deprecated_since='17.0.0',
deprecated_reason="""
Monkey patching nova is not tested, not supported, and is a barrier
for interoperability.
""",
help="""
Determine if monkey patching should be applied.
Related options:
* ``monkey_patch_modules``: This must have values set for this option to
have any effect
"""),
cfg.ListOpt(
'monkey_patch_modules',
default=['nova.compute.api:nova.notifications.notify_decorator'],
deprecated_for_removal=True,
deprecated_since='17.0.0',
deprecated_reason="""
Monkey patching nova is not tested, not supported, and is a barrier
for interoperability.
""",
help="""
List of modules/decorators to monkey patch.
This option allows you to patch a decorator for all functions in specified
modules.
Possible values:
* nova.compute.api:nova.notifications.notify_decorator
* [...]
Related options:
* ``monkey_patch``: This must be set to ``True`` for this option to
have any effect
"""),
] ]

View File

@ -57,32 +57,6 @@ Possible values:
deprecated_group='DEFAULT', deprecated_group='DEFAULT',
deprecated_name='default_notification_level', deprecated_name='default_notification_level',
help="Default notification level for outgoing notifications."), help="Default notification level for outgoing notifications."),
cfg.StrOpt(
'default_publisher_id',
default='$host',
deprecated_group='DEFAULT',
deprecated_for_removal=True,
deprecated_since='17.0.0',
deprecated_reason="""
This option is only used when ``monkey_patch=True`` and
``monkey_patch_modules`` is configured to specify the legacy notify_decorator.
Since the monkey_patch and monkey_patch_modules options are deprecated, this
option is also deprecated.
""",
help="""
Default publisher_id for outgoing notifications. If you consider routing
notifications using different publisher, change this value accordingly.
Possible values:
* Defaults to the current hostname of this host, but it can be any valid
oslo.messaging publisher_id
Related options:
* host - Hostname, FQDN or IP address of this host.
"""),
cfg.StrOpt( cfg.StrOpt(
'notification_format', 'notification_format',
choices=['unversioned', 'versioned', 'both'], choices=['unversioned', 'versioned', 'both'],

View File

@ -21,6 +21,5 @@ from nova.notifications.base import audit_period_bounds # noqa
from nova.notifications.base import bandwidth_usage # noqa from nova.notifications.base import bandwidth_usage # noqa
from nova.notifications.base import image_meta # noqa from nova.notifications.base import image_meta # noqa
from nova.notifications.base import info_from_instance # noqa from nova.notifications.base import info_from_instance # noqa
from nova.notifications.base import notify_decorator # noqa
from nova.notifications.base import send_update # noqa from nova.notifications.base import send_update # noqa
from nova.notifications.base import send_update_with_states # noqa from nova.notifications.base import send_update_with_states # noqa

View File

@ -21,7 +21,6 @@ the system.
import datetime import datetime
from keystoneauth1 import exceptions as ks_exc from keystoneauth1 import exceptions as ks_exc
from oslo_context import context as common_context
from oslo_log import log from oslo_log import log
from oslo_utils import excutils from oslo_utils import excutils
from oslo_utils import timeutils from oslo_utils import timeutils
@ -46,41 +45,6 @@ LOG = log.getLogger(__name__)
CONF = nova.conf.CONF CONF = nova.conf.CONF
# TODO(mriedem): Remove this when CONF.monkey_patch, CONF.monkey_patch_modules
# and CONF.default_publisher_id are removed in Rocky.
def notify_decorator(name, fn):
"""Decorator for notify which is used from utils.monkey_patch().
:param name: name of the function
:param fn: - object of the function
:returns: fn -- decorated function
"""
def wrapped_func(*args, **kwarg):
body = {}
body['args'] = []
body['kwarg'] = {}
for arg in args:
body['args'].append(arg)
for key in kwarg:
body['kwarg'][key] = kwarg[key]
ctxt = (common_context.get_context_from_function_and_args(
fn, args, kwarg) or
common_context.get_current() or
nova.context.RequestContext())
notifier = rpc.get_notifier('api', publisher_id=(
CONF.notifications.default_publisher_id or CONF.host))
method = getattr(notifier,
CONF.notifications.default_level.lower(),
notifier.info)
method(ctxt, name, body)
return fn(*args, **kwarg)
return wrapped_func
def send_update(context, old_instance, new_instance, service="compute", def send_update(context, old_instance, new_instance, service="compute",
host=None): host=None):
"""Send compute.instance.update notification to report any changes occurred """Send compute.instance.update notification to report any changes occurred

View File

@ -33,10 +33,9 @@ def restore_db():
class ComputeMainTest(test.NoDBTestCase): class ComputeMainTest(test.NoDBTestCase):
@mock.patch('nova.utils.monkey_patch')
@mock.patch('nova.conductor.api.API.wait_until_ready') @mock.patch('nova.conductor.api.API.wait_until_ready')
@mock.patch('oslo_reports.guru_meditation_report') @mock.patch('oslo_reports.guru_meditation_report')
def _call_main(self, mod, gmr, cond, patch): def _call_main(self, mod, gmr, cond):
@mock.patch.object(mod, 'config') @mock.patch.object(mod, 'config')
@mock.patch.object(mod, 'service') @mock.patch.object(mod, 'service')
def run_main(serv, conf): def run_main(serv, conf):

View File

@ -1,31 +0,0 @@
# Copyright 2011 OpenStack Foundation
# All Rights Reserved.
#
# 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.
"""Example Module for testing utils.monkey_patch()."""
CALLED_FUNCTION = []
def example_decorator(name, function):
"""decorator for notify which is used from utils.monkey_patch()
:param name: name of the function
:param function: - object of the function
:returns: function -- decorated function
"""
def wrapped_func(*args, **kwarg):
CALLED_FUNCTION.append(name)
return function(*args, **kwarg)
return wrapped_func

View File

@ -1,27 +0,0 @@
# Copyright 2011 OpenStack Foundation
# All Rights Reserved.
#
# 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.
"""Example Module A for testing utils.monkey_patch()."""
def example_function_a():
return 'Example function'
class ExampleClassA(object):
def example_method(self):
return 'Example method'
def example_method_add(self, arg1, arg2):
return arg1 + arg2

View File

@ -1,28 +0,0 @@
# Copyright 2011 OpenStack Foundation
# All Rights Reserved.
#
# 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.
"""Example Module B for testing utils.monkey_patch()."""
def example_function_b():
return 'Example function'
class ExampleClassB(object):
def example_method(self):
return 'Example method'
def example_method_add(self, arg1, arg2):
return arg1 + arg2

View File

@ -20,7 +20,6 @@ import datetime
import mock import mock
from oslo_config import cfg from oslo_config import cfg
from oslo_context import context as o_context
from oslo_context import fixture as o_fixture from oslo_context import fixture as o_fixture
from oslo_utils import timeutils from oslo_utils import timeutils
@ -519,26 +518,6 @@ class NotificationsTestCase(test.TestCase):
def _decorated_function(self, arg1, arg2): def _decorated_function(self, arg1, arg2):
self.decorated_function_called = True self.decorated_function_called = True
def test_notify_decorator(self):
func_name = self._decorated_function.__name__
# Decorated with notify_decorator like monkey_patch
self._decorated_function = notifications.notify_decorator(
func_name,
self._decorated_function)
ctxt = o_context.RequestContext()
self._decorated_function(1, ctxt)
self.assertEqual(1, len(fake_notifier.NOTIFICATIONS))
n = fake_notifier.NOTIFICATIONS[0]
self.assertEqual(n.priority, 'INFO')
self.assertEqual(n.event_type, func_name)
self.assertEqual(n.context, ctxt)
self.assertTrue(self.decorated_function_called)
self.assertEqual(CONF.host, n.publisher_id)
class NotificationsFormatTestCase(test.NoDBTestCase): class NotificationsFormatTestCase(test.NoDBTestCase):

View File

@ -14,7 +14,6 @@
import datetime import datetime
import hashlib import hashlib
import importlib
import os import os
import os.path import os.path
import tempfile import tempfile
@ -36,7 +35,6 @@ from oslo_utils import fixture as utils_fixture
from oslo_utils import units from oslo_utils import units
import six import six
import nova
from nova import context from nova import context
from nova import exception from nova import exception
from nova.objects import base as obj_base from nova.objects import base as obj_base
@ -457,74 +455,6 @@ Exit code: -2''')
mock.call(['a', '1'], None)]) mock.call(['a', '1'], None)])
class MonkeyPatchTestCase(test.NoDBTestCase):
"""Unit test for utils.monkey_patch()."""
def setUp(self):
super(MonkeyPatchTestCase, self).setUp()
self.example_package = 'nova.tests.unit.monkey_patch_example.'
self.flags(
monkey_patch=True,
monkey_patch_modules=[self.example_package + 'example_a' + ':'
+ self.example_package + 'example_decorator'])
def test_monkey_patch(self):
utils.monkey_patch()
nova.tests.unit.monkey_patch_example.CALLED_FUNCTION = []
from nova.tests.unit.monkey_patch_example import example_a
from nova.tests.unit.monkey_patch_example import example_b
self.assertEqual('Example function', example_a.example_function_a())
exampleA = example_a.ExampleClassA()
exampleA.example_method()
ret_a = exampleA.example_method_add(3, 5)
self.assertEqual(ret_a, 8)
self.assertEqual('Example function', example_b.example_function_b())
exampleB = example_b.ExampleClassB()
exampleB.example_method()
ret_b = exampleB.example_method_add(3, 5)
self.assertEqual(ret_b, 8)
package_a = self.example_package + 'example_a.'
self.assertIn(package_a + 'example_function_a',
nova.tests.unit.monkey_patch_example.CALLED_FUNCTION)
self.assertIn(package_a + 'ExampleClassA.example_method',
nova.tests.unit.monkey_patch_example.CALLED_FUNCTION)
self.assertIn(package_a + 'ExampleClassA.example_method_add',
nova.tests.unit.monkey_patch_example.CALLED_FUNCTION)
package_b = self.example_package + 'example_b.'
self.assertNotIn(package_b + 'example_function_b',
nova.tests.unit.monkey_patch_example.CALLED_FUNCTION)
self.assertNotIn(package_b + 'ExampleClassB.example_method',
nova.tests.unit.monkey_patch_example.CALLED_FUNCTION)
self.assertNotIn(package_b + 'ExampleClassB.example_method_add',
nova.tests.unit.monkey_patch_example.CALLED_FUNCTION)
class MonkeyPatchDefaultTestCase(test.NoDBTestCase):
"""Unit test for default monkey_patch_modules value."""
def setUp(self):
super(MonkeyPatchDefaultTestCase, self).setUp()
self.flags(
monkey_patch=True)
def test_monkey_patch_default_mod(self):
# monkey_patch_modules is defined to be
# <module_to_patch>:<decorator_to_patch_with>
# Here we check that both parts of the default values are
# valid
for module in CONF.monkey_patch_modules:
m = module.split(':', 1)
# Check we can import the module to be patched
importlib.import_module(m[0])
# check the decorator is valid
decorator_name = m[1].rsplit('.', 1)
decorator_module = importlib.import_module(decorator_name[0])
getattr(decorator_module, decorator_name[1])
class AuditPeriodTest(test.NoDBTestCase): class AuditPeriodTest(test.NoDBTestCase):
def setUp(self): def setUp(self):

View File

@ -24,11 +24,9 @@ import functools
import hashlib import hashlib
import inspect import inspect
import os import os
import pyclbr
import random import random
import re import re
import shutil import shutil
import sys
import tempfile import tempfile
import time import time
@ -469,55 +467,6 @@ def format_remote_path(host, path):
return "%s:%s" % (safe_ip_format(host), path) return "%s:%s" % (safe_ip_format(host), path)
# TODO(mriedem): Remove this in Rocky.
def monkey_patch():
"""DEPRECATED: If the CONF.monkey_patch set as True,
this function patches a decorator
for all functions in specified modules.
You can set decorators for each modules
using CONF.monkey_patch_modules.
The format is "Module path:Decorator function".
Example:
'nova.api.ec2.cloud:nova.notifications.notify_decorator'
Parameters of the decorator is as follows.
(See nova.notifications.notify_decorator)
name - name of the function
function - object of the function
"""
# If CONF.monkey_patch is not True, this function do nothing.
if not CONF.monkey_patch:
return
LOG.warning('Monkey patching nova is deprecated for removal.')
if six.PY2:
is_method = inspect.ismethod
else:
def is_method(obj):
# Unbound methods became regular functions on Python 3
return inspect.ismethod(obj) or inspect.isfunction(obj)
# Get list of modules and decorators
for module_and_decorator in CONF.monkey_patch_modules:
module, decorator_name = module_and_decorator.split(':')
# import decorator function
decorator = importutils.import_class(decorator_name)
__import__(module)
# Retrieve module information using pyclbr
module_data = pyclbr.readmodule_ex(module)
for key, value in module_data.items():
# set the decorator for the class methods
if isinstance(value, pyclbr.Class):
clz = importutils.import_class("%s.%s" % (module, key))
for method, func in inspect.getmembers(clz, is_method):
setattr(clz, method,
decorator("%s.%s.%s" % (module, key, method), func))
# set the decorator for the function
if isinstance(value, pyclbr.Function):
func = importutils.import_class("%s.%s" % (module, key))
setattr(sys.modules[module], key,
decorator("%s.%s" % (module, key), func))
def make_dev_path(dev, partition=None, base='/dev'): def make_dev_path(dev, partition=None, base='/dev'):
"""Return a path to a particular device. """Return a path to a particular device.

View File

@ -0,0 +1,14 @@
---
upgrade:
- |
The following configuration options were deprecated for removal in the
17.0.0 Queens release and have now been removed:
- ``[DEFAULT]/monkey_patch``
- ``[DEFAULT]/monkey_patch_modules``
- ``[notifications]/default_publisher_id``
Monkey patching nova is not tested, not supported, and is a barrier to
interoperability. If you have code which relies on monkey patching
decorators, for example, for notifications, please propose those changes
upstream.

View File

@ -44,7 +44,6 @@ if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'nova', '__init__.py')):
import nova.conf import nova.conf
from nova import config from nova import config
from nova import utils
from nova.virt.xenapi import vm_utils from nova.virt.xenapi import vm_utils
destroy_opts = [ destroy_opts = [
@ -66,7 +65,6 @@ CONF.register_cli_opts(destroy_opts)
def main(): def main():
config.parse_args(sys.argv) config.parse_args(sys.argv)
utils.monkey_patch()
_session = session.XenAPISession(CONF.xenserver.connection_url, _session = session.XenAPISession(CONF.xenserver.connection_url,
CONF.xenserver.connection_username, CONF.xenserver.connection_username,