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 objects
from nova import service
from nova import utils
CONF = cfg.CONF
CONFIG_FILES = ['api-paste.ini', 'nova.conf']
utils.monkey_patch()
objects.register_all()

View File

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

View File

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

View File

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

View File

@ -43,7 +43,6 @@ def main():
config.parse_args(sys.argv)
logging.setup(CONF, 'nova')
priv_context.init(root_helper=shlex.split(utils.get_root_helper()))
utils.monkey_patch()
objects.register_all()
gmr_opts.set_defaults(CONF)
# 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 objects
from nova import service
from nova import utils
from nova import version
CONF = nova.conf.CONF
@ -35,7 +34,6 @@ CONF = nova.conf.CONF
def main():
config.parse_args(sys.argv)
logging.setup(CONF, "nova")
utils.monkey_patch()
objects.register_all()
gmr_opts.set_defaults(CONF)
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.objects import base as objects_base
from nova import service
from nova import utils
from nova import version
CONF = nova.conf.CONF
@ -46,7 +45,6 @@ def main():
'except as required for CellsV1 deployments.')
return 1
utils.monkey_patch()
objects.register_all()
gmr_opts.set_defaults(CONF)

View File

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

View File

@ -60,48 +60,6 @@ entry.
cfg.StrOpt(
'tempdir',
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_name='default_notification_level',
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(
'notification_format',
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 image_meta # 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_with_states # noqa

View File

@ -21,7 +21,6 @@ the system.
import datetime
from keystoneauth1 import exceptions as ks_exc
from oslo_context import context as common_context
from oslo_log import log
from oslo_utils import excutils
from oslo_utils import timeutils
@ -46,41 +45,6 @@ LOG = log.getLogger(__name__)
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",
host=None):
"""Send compute.instance.update notification to report any changes occurred

View File

@ -33,10 +33,9 @@ def restore_db():
class ComputeMainTest(test.NoDBTestCase):
@mock.patch('nova.utils.monkey_patch')
@mock.patch('nova.conductor.api.API.wait_until_ready')
@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, 'service')
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
from oslo_config import cfg
from oslo_context import context as o_context
from oslo_context import fixture as o_fixture
from oslo_utils import timeutils
@ -519,26 +518,6 @@ class NotificationsTestCase(test.TestCase):
def _decorated_function(self, arg1, arg2):
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):

View File

@ -14,7 +14,6 @@
import datetime
import hashlib
import importlib
import os
import os.path
import tempfile
@ -36,7 +35,6 @@ from oslo_utils import fixture as utils_fixture
from oslo_utils import units
import six
import nova
from nova import context
from nova import exception
from nova.objects import base as obj_base
@ -457,74 +455,6 @@ Exit code: -2''')
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):
def setUp(self):

View File

@ -24,11 +24,9 @@ import functools
import hashlib
import inspect
import os
import pyclbr
import random
import re
import shutil
import sys
import tempfile
import time
@ -469,55 +467,6 @@ def format_remote_path(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'):
"""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
from nova import config
from nova import utils
from nova.virt.xenapi import vm_utils
destroy_opts = [
@ -66,7 +65,6 @@ CONF.register_cli_opts(destroy_opts)
def main():
config.parse_args(sys.argv)
utils.monkey_patch()
_session = session.XenAPISession(CONF.xenserver.connection_url,
CONF.xenserver.connection_username,