diff --git a/HACKING.rst b/HACKING.rst index 1246575d84e..84f6f3e1c77 100644 --- a/HACKING.rst +++ b/HACKING.rst @@ -8,7 +8,7 @@ Neutron Style Commandments Neutron Specific Commandments -------------------------- -None so far +- [N320] Validate that LOG messages, except debug ones, have translations Creating Unit Tests ------------------- diff --git a/neutron/agent/securitygroups_rpc.py b/neutron/agent/securitygroups_rpc.py index e8dc68209b9..7d476729c40 100644 --- a/neutron/agent/securitygroups_rpc.py +++ b/neutron/agent/securitygroups_rpc.py @@ -56,7 +56,8 @@ def _is_valid_driver_combination(): def is_firewall_enabled(): if not _is_valid_driver_combination(): - LOG.warn("Driver configuration don't match with enable_security_group") + LOG.warn(_("Driver configuration doesn't match with " + "enable_security_group")) return cfg.CONF.SECURITYGROUP.enable_security_group @@ -139,8 +140,8 @@ class SecurityGroupAgentRpcMixin(object): firewall_driver = cfg.CONF.SECURITYGROUP.firewall_driver LOG.debug(_("Init firewall settings (driver=%s)"), firewall_driver) if not _is_valid_driver_combination(): - LOG.warn("Driver configuration doesn't match " - "with enable_security_group") + LOG.warn(_("Driver configuration doesn't match " + "with enable_security_group")) if not firewall_driver: firewall_driver = 'neutron.agent.firewall.NoopFirewallDriver' self.firewall = importutils.import_object(firewall_driver) diff --git a/neutron/hacking/__init__.py b/neutron/hacking/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/neutron/hacking/checks.py b/neutron/hacking/checks.py new file mode 100644 index 00000000000..899d7624306 --- /dev/null +++ b/neutron/hacking/checks.py @@ -0,0 +1,50 @@ +# Copyright (c) 2014 OpenStack Foundation. +# +# 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. + +import re + +import pep8 + +""" +Guidelines for writing new hacking checks + + - Use only for Neutron specific tests. OpenStack general tests + should be submitted to the common 'hacking' module. + - Pick numbers in the range N3xx. Find the current test with + the highest allocated number and then pick the next value. + - Keep the test method code in the source file ordered based + on the N3xx value. + - List the new rule in the top level HACKING.rst file + - Add test cases for each new rule to + neutron/tests/unit/test_hacking.py + +""" + +log_translation = re.compile( + r"(.)*LOG\.(audit|error|info|warn|warning|critical|exception)\(\s*('|\")") + + +def validate_log_translations(logical_line, physical_line, filename): + # Translations are not required in the test directory + if "neutron/tests" in filename: + return + if pep8.noqa(physical_line): + return + msg = "N320: Log messages require translations!" + if log_translation.match(logical_line): + yield (0, msg) + + +def factory(register): + register(validate_log_translations) diff --git a/neutron/plugins/hyperv/agent/security_groups_driver.py b/neutron/plugins/hyperv/agent/security_groups_driver.py index 9c997f18baf..755ab5270ed 100644 --- a/neutron/plugins/hyperv/agent/security_groups_driver.py +++ b/neutron/plugins/hyperv/agent/security_groups_driver.py @@ -89,10 +89,10 @@ class HyperVSecurityGroupsDriver(firewall.FirewallDriver): } def apply_port_filter(self, port): - LOG.info('Aplying port filter.') + LOG.info(_('Aplying port filter.')) def update_port_filter(self, port): - LOG.info('Updating port rules.') + LOG.info(_('Updating port rules.')) if port['device'] not in self._security_ports: self.prepare_port_filter(port) @@ -105,8 +105,10 @@ class HyperVSecurityGroupsDriver(firewall.FirewallDriver): new_rules = [r for r in param_port_rules if r not in rules] remove_rules = [r for r in rules if r not in param_port_rules] - LOG.info("Creating %s new rules, removing %s old rules." % ( - len(new_rules), len(remove_rules))) + LOG.info(_("Creating %(new)s new rules, removing %(old)s " + "old rules."), + {'new': len(new_rules), + 'old': len(remove_rules)}) self._remove_port_rules(old_port['id'], remove_rules) self._create_port_rules(port['id'], new_rules) @@ -114,7 +116,7 @@ class HyperVSecurityGroupsDriver(firewall.FirewallDriver): self._security_ports[port['device']] = port def remove_port_filter(self, port): - LOG.info('Removing port filter') + LOG.info(_('Removing port filter')) self._security_ports.pop(port['device'], None) @property diff --git a/neutron/plugins/hyperv/agent/utilsfactory.py b/neutron/plugins/hyperv/agent/utilsfactory.py index 8b6ae77293f..5698255c33e 100644 --- a/neutron/plugins/hyperv/agent/utilsfactory.py +++ b/neutron/plugins/hyperv/agent/utilsfactory.py @@ -60,8 +60,8 @@ def get_hypervutils(): force_v1_flag = CONF.hyperv.force_hyperv_utils_v1 if _check_min_windows_version(6, 3): if force_v1_flag: - LOG.warning('V1 virtualization namespace no longer supported on ' - 'Windows Server / Hyper-V Server 2012 R2 or above.') + LOG.warning(_('V1 virtualization namespace no longer supported on ' + 'Windows Server / Hyper-V Server 2012 R2 or above.')) cls = utilsv2.HyperVUtilsV2R2 elif not force_v1_flag and _check_min_windows_version(6, 2): cls = utilsv2.HyperVUtilsV2 diff --git a/neutron/plugins/plumgrid/plumgrid_plugin/plumgrid_plugin.py b/neutron/plugins/plumgrid/plumgrid_plugin/plumgrid_plugin.py index 330c98b41f7..d28b90ae0e7 100644 --- a/neutron/plugins/plumgrid/plumgrid_plugin/plumgrid_plugin.py +++ b/neutron/plugins/plumgrid/plumgrid_plugin/plumgrid_plugin.py @@ -570,8 +570,8 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2, def _network_admin_state(self, network): if network["network"].get("admin_state_up") is False: - LOG.warning("Networks with admin_state_up=False are not " - "supported by PLUMgrid plugin yet.") + LOG.warning(_("Networks with admin_state_up=False are not " + "supported by PLUMgrid plugin yet.")) return network def _allocate_pools_for_subnet(self, context, subnet): diff --git a/neutron/tests/unit/test_hacking.py b/neutron/tests/unit/test_hacking.py new file mode 100644 index 00000000000..a5cebd1aaf2 --- /dev/null +++ b/neutron/tests/unit/test_hacking.py @@ -0,0 +1,43 @@ +# 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. + +from neutron.hacking import checks +from neutron.tests import base + + +class HackingTestCase(base.BaseTestCase): + + def test_log_translations(self): + logs = ['audit', 'error', 'info', 'warn', 'warning', 'critical', + 'exception'] + levels = ['_LI', '_LW', '_LE', '_LC'] + debug = "LOG.debug('OK')" + self.assertEqual( + 0, len(list(checks.validate_log_translations(debug, debug, 'f')))) + for log in logs: + bad = 'LOG.%s("Bad")' % log + self.assertEqual( + 1, len(list(checks.validate_log_translations(bad, bad, 'f')))) + ok = "LOG.%s(_('OK'))" % log + self.assertEqual( + 0, len(list(checks.validate_log_translations(ok, ok, 'f')))) + ok = "LOG.%s('OK') # noqa" % log + self.assertEqual( + 0, len(list(checks.validate_log_translations(ok, ok, 'f')))) + ok = "LOG.%s(variable)" % log + self.assertEqual( + 0, len(list(checks.validate_log_translations(ok, ok, 'f')))) + for level in levels: + ok = "LOG.%s(%s('OK'))" % (log, level) + self.assertEqual( + 0, len(list(checks.validate_log_translations(ok, + ok, 'f')))) diff --git a/tox.ini b/tox.ini index 028f8865f22..297998a8c2f 100644 --- a/tox.ini +++ b/tox.ini @@ -46,3 +46,6 @@ ignore = E125,H404 show-source = true builtins = _ exclude = .venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,tools,.ropeproject + +[hacking] +local-check-factory = neutron.hacking.checks.factory