修复 log 和 versionutils 之间的导入循环¶
https://blueprints.launchpad.net/oslo-incubator/+spec/fix-import-cycle-log-and-versionutils
打破导入循环,以便我们可以发布 oslo.log。
问题描述¶
versionutils 和日志记录代码之间存在循环依赖,它们计划被发布为独立的库。我们需要打破这个循环,以便 oslo.log 能够在此周期内毕业。
提议的变更¶
oslo-incubator¶
将 ContextAdapter.deprecated() 方法移动到 versionutils 中的一个函数,与其他的弃用相关代码一起。这意味着将 fatal_deprecations 配置选项移动过去,并更新所有调用者。
建议的函数签名是
# versionutils.py
def report_deprecated_feature(logger, msg, *args, **kwds):
"""Call this function when a deprecated feature is used.
If the system is configured for fatal deprecations then the message
is logged at the 'critical' level and :class:`DeprecatedConfig` will
be raised.
Otherwise, the message will be logged (once) at the 'warn' level.
:param logger: The Python logger to use to generate the message.
:type logger: logging.Logger
:param msg: The message to emit.
:type msg: unicode
:raises: :class:`DeprecatedConfig` if the system is configured for
fatal deprecations.
"""
为了保持当前的日志记录行为,report_deprecated_feature() 将接受一个 logger 作为参数,并使用它来发出消息(而不是拥有一个名称为 versionutils 模块的单个 logger)。
将 fatal_deprecations 从默认选项组移动到 deprecation 组,并带有适当的弃用设置,以便在找到旧名称时能够识别它。
更新 versionutils.deprecated() 以调用 report_deprecated_feature() 而不是 LOG.deprecated()。
oslo.log¶
完全从 oslo.log 中删除所有与弃用相关的代码。它将保留在 versionutils 中,要么在 incubator 中,要么在一个新的库中,这将在另一个蓝图讨论。
备选方案¶
更改 versionutils 中 deprecated() 装饰器的实现,使其不再调用 LOG.deprecated()。这可能意味着复制 LOG.deprecated() 中的逻辑。
将 LOG.deprecated() 的大部分主体移动到 versionutils,但保留该方法。这限制了我们必须在调用者中进行的更改数量,但这意味着 oslo.log 依赖于 oslo.versionutils。我们可以通过让 versionutils 中的函数使用 python 的标准 logger 而不是 oslo.log 来消除循环依赖。这似乎符合 oslo.log 上面的 API 更改。
这两种替代方案都可以修复循环,但要求我们保留 LOG.deprecated() 和我们的特殊 ContextAdapter。我们正在尝试在另一个与 oslo.log 毕业相关的蓝图中删除该类。
Impact on Existing APIs¶
LOG.deprecated() 的调用者需要更新为使用 versionutils.report_deprecated_feature() 代替。
安全影响¶
无
性能影响¶
无
Configuration Impact¶
将 fatal_deprecations 从默认选项组移动到 versionutils 组。
开发人员影响¶
报告弃用代码和功能的 API 将移动到一个新的位置,因此我们需要公开此更改。应用程序可以在与 incubator 中的日志记录和 versionutils 代码同步更改时进行更新。
大多数调用者无论如何都使用 deprecated() 装饰器。
更新调用的搜索
oslo-incubator/tests/unit/test_deprecated.py
38: def test_deprecated(self):
39: LOG.deprecated('test')
54: LOG.deprecated('only once!')
55: LOG.deprecated('only once!')
56: LOG.deprecated('only once!')
65: LOG.deprecated(msg1)
66: LOG.deprecated(msg2)
67: LOG.deprecated(msg1)
68: LOG.deprecated(msg1)
69: LOG.deprecated(msg2)
70: LOG.deprecated(msg2)
83: LOG.deprecated('only once! %s', 'arg1')
84: LOG.deprecated('only once! %s', 'arg1')
85: LOG.deprecated('only once! %s', 'arg2')
86: LOG.deprecated('only once! %s', 'arg2')
108: LOG.deprecated(msg_fmt_1, msg_fmt_1_arg_1)
109: LOG.deprecated(msg_fmt_1, msg_fmt_1_arg_2) # logged: args different
110: LOG.deprecated(msg_fmt_1, msg_fmt_1_arg_1) # no log: same msg+args
112: LOG.deprecated(msg_fmt_2, msg_fmt_2_arg_1)
113: LOG.deprecated(msg_fmt_2, *msg_fmt_2_arg_2) # logged: args different
114: LOG.deprecated(msg_fmt_2, *msg_fmt_2_arg_3) # logged: args different
115: LOG.deprecated(msg_fmt_2, *msg_fmt_2_arg_3) # no log: same msg+args
116: LOG.deprecated(msg_fmt_2, *msg_fmt_2_arg_2) # no log: same msg+args
cinder/cinder/api/contrib/services.py
91: LOG.deprecated(_("Query by service parameter is deprecated. "
cinder/cinder/quota.py
106: LOG.deprecated(_("Default quota for resource: %(res)s is set "
cinder/cinder/scheduler/manager.py
66: LOG.deprecated(_('ChanceScheduler and SimpleScheduler have been '
neutron/neutron/plugins/vmware/nsx_cluster.py
49: LOG.deprecated(_("Attribute '%s' has been deprecated or moved "
neutron/neutron/agent/common/config.py
104: LOG.deprecated(_('DEFAULT.root_helper is deprecated! Please move '
glance/glance/store/__init__.py
200: LOG.deprecated(_("%s not found in `known_store`. "
搜索用法
$ ack --ignore-dir=.tox --ignore-dir=build --ignore-dir=.venv \
--ignore-dir=.update-venv --ignore-dir=openstack 'deprecated\('
python-keystoneclient/keystoneclient/tests/test_discovery.py
673: def test_allow_deprecated(self):
python-keystoneclient/keystoneclient/tests/test_http.py
136: def test_client_deprecated(self):
keystone/keystone/catalog/backends/templated.py
128:@versionutils.deprecated(
keystone/keystone/contrib/stats/core.py
130: @versionutils.deprecated(
keystone/keystone/contrib/access/core.py
35: @versionutils.deprecated(
keystone/keystone/middleware/s3_token.py
50: @versionutils.deprecated(
keystone/keystone/middleware/core.py
148: @versionutils.deprecated(
keystone/keystone/auth/plugins/external.py
102: @versionutils.deprecated(
113: @versionutils.deprecated(
130: @versionutils.deprecated(
151: @versionutils.deprecated(
keystone/keystone/token/core.py
263: @versionutils.deprecated(versionutils.deprecated.ICEHOUSE, remove_in=+1)
keystone/keystone/common/controller.py
33:def v2_deprecated(f):
42: v2_deprecated = versionutils.deprecated(
keystone/keystone/common/kvs/legacy.py
49: @versionutils.deprecated(versionutils.deprecated.ICEHOUSE,
keystone/vendor/python-keystoneclient-master/keystoneclient/tests/test_http.py
136: def test_client_deprecated(self):
oslo-incubator/tests/unit/test_versionutils.py
24: def assert_deprecated(self, mock_log, **expected_details):
35: @versionutils.deprecated(as_of=versionutils.deprecated.ICEHOUSE)
48: @versionutils.deprecated(as_of=versionutils.deprecated.ICEHOUSE)
59: @versionutils.deprecated(as_of=versionutils.deprecated.ICEHOUSE,
66: self.assert_deprecated(mock_log,
75: @versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY,
82: self.assert_deprecated(mock_log,
91: @versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY)
97: self.assert_deprecated(mock_log,
105: @versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY,
113: self.assert_deprecated(mock_log,
122: @versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY,
129: self.assert_deprecated(mock_log,
137: @versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY,
144: self.assert_deprecated(mock_log,
oslo-incubator/tests/unit/test_log.py
600: def test_logfile_deprecated(self):
610: def test_logdir_deprecated(self):
oslo-incubator/tests/unit/test_deprecated.py
38: def test_deprecated(self):
39: LOG.deprecated('test')
54: LOG.deprecated('only once!')
55: LOG.deprecated('only once!')
56: LOG.deprecated('only once!')
65: LOG.deprecated(msg1)
66: LOG.deprecated(msg2)
67: LOG.deprecated(msg1)
68: LOG.deprecated(msg1)
69: LOG.deprecated(msg2)
70: LOG.deprecated(msg2)
83: LOG.deprecated('only once! %s', 'arg1')
84: LOG.deprecated('only once! %s', 'arg1')
85: LOG.deprecated('only once! %s', 'arg2')
86: LOG.deprecated('only once! %s', 'arg2')
108: LOG.deprecated(msg_fmt_1, msg_fmt_1_arg_1)
109: LOG.deprecated(msg_fmt_1, msg_fmt_1_arg_2) # logged: args different
110: LOG.deprecated(msg_fmt_1, msg_fmt_1_arg_1) # no log: same msg+args
112: LOG.deprecated(msg_fmt_2, msg_fmt_2_arg_1)
113: LOG.deprecated(msg_fmt_2, *msg_fmt_2_arg_2) # logged: args different
114: LOG.deprecated(msg_fmt_2, *msg_fmt_2_arg_3) # logged: args different
115: LOG.deprecated(msg_fmt_2, *msg_fmt_2_arg_3) # no log: same msg+args
116: LOG.deprecated(msg_fmt_2, *msg_fmt_2_arg_2) # no log: same msg+args
cinder/cinder/api/contrib/services.py
91: LOG.deprecated(_("Query by service parameter is deprecated. "
cinder/cinder/quota.py
106: LOG.deprecated(_("Default quota for resource: %(res)s is set "
cinder/cinder/scheduler/manager.py
66: LOG.deprecated(_('ChanceScheduler and SimpleScheduler have been '
oslo.config/tests/test_cfg.py
654: def test_conf_file_str_value_override_use_deprecated(self):
1086: def test_conf_file_dict_values_override_deprecated(self):
1106: def test_conf_file_dict_deprecated(self):
1232: def test_conf_file_multistr_values_append_deprecated(self):
1271: def test_conf_file_multistr_deprecated(self):
neutron/neutron/plugins/vmware/nsx_cluster.py
49: LOG.deprecated(_("Attribute '%s' has been deprecated or moved "
neutron/neutron/agent/common/config.py
104: LOG.deprecated(_('DEFAULT.root_helper is deprecated! Please move '
heat/heat/tests/test_neutron_loadbalancer.py
429: def test_create_deprecated(self):
heat/heat/tests/test_neutron_vpnservice.py
201: def test_create_deprecated(self):
heat/heat/tests/test_parser.py
759: def test_stack_resolve_runtime_data_deprecated(self):
heat/heat/tests/test_engine_service.py
1950: def test_list_resource_types_deprecated(self):
heat/heat/tests/test_neutron.py
914: def test_subnet_deprecated(self):
1387: def test_router_interface_deprecated(self):
1801: def test_floating_ip_deprecated(self):
heat/heat/tests/test_neutron_network_gateway.py
233: def test_network_gateway_create_deprecated(self):
os-refresh-config/os_refresh_config/tests/test_os_refresh_config.py
27: def test_default_base_dir_deprecated(self):
glance/glance/store/__init__.py
200: LOG.deprecated(_("%s not found in `known_store`. "
os-apply-config/os_apply_config/tests/test_apply_config.py
293: def test_default_templates_dir_deprecated(self):
298: def test_default_templates_dir_old_deprecated(self):
实现¶
负责人¶
- 主要负责人
Doug Hellmann (doug-hellmann)
- 其他贡献者
无
里程碑¶
完成目标里程碑:Juno-1
工作项¶
将
ContextAdapter.deprecated()移动到log_deprecated_feature()并更新实现。移动
fatal_deprecations选项定义的地点以及注册它的组。更新 Cinder。
更新 Neutron。
更新 Glance。
孵化¶
N/A
采用¶
N/A
库¶
N/A
预计 API 稳定¶
这个新的 API 应该足够稳定,以便 oslo.versionutils 能够毕业。这项工作将由一个单独的规范/蓝图跟踪。
文档影响¶
配置选项正在移动到一个新的组,因此文档中生成的示例配置文件和配置表需要更新。
依赖项¶
无
参考资料¶
注意
本作品采用知识共享署名 3.0 非移植许可协议授权。 http://creativecommons.org/licenses/by/3.0/legalcode