Add missing translation support

Update a number of files to add missing translation support.

The patch adds a new hacking check - N321. This ensures that
all log messages, except debug ones, have translations.

A '# noqa' indicates that the validation will not be done on
the specific log message. This should be used in cases where
the translations do not need to be done, for example, the log
message is logging raw data.

Closes-bug: #1290261
Change-Id: Ib2ca0bfaaf432e15448c96619682c2cfd073fbbc
This commit is contained in:
Gary Kotton 2014-03-02 00:04:24 -08:00
parent 5d7ac6a928
commit b4ef81d6a0
9 changed files with 63 additions and 10 deletions

View File

@ -33,6 +33,7 @@ Nova Specific Commandments
- [N319] Validate that debug level logs are not translated.
- [N320] Setting CONF.* attributes directly in tests is forbidden. Use
self.flags(option=value) instead.
- [N321] Validate that LOG messages, except debug ones, have translations
Creating Unit Tests
-------------------

View File

@ -123,7 +123,7 @@ class RequestLogging(wsgi.Middleware):
request.user_agent,
request.content_type,
response.content_type,
context=ctxt)
context=ctxt) # noqa
class Lockout(wsgi.Middleware):

View File

@ -292,7 +292,7 @@ class APIRouterV3(base_wsgi.Router):
return False
if not CONF.osapi_v3.enabled:
LOG.info("V3 API has been disabled by configuration")
LOG.info(_("V3 API has been disabled by configuration"))
return
self.init_only = init_only

View File

@ -2024,7 +2024,8 @@ class ComputeManager(manager.Manager):
except Exception:
# Because this allocation is async any failures are likely to occur
# when the driver accesses network_info during spawn().
LOG.exception('Failed to allocate network(s)', instance=instance)
LOG.exception(_('Failed to allocate network(s)'),
instance=instance)
msg = _('Failed to allocate the network(s), not rescheduling.')
raise exception.BuildAbortException(instance_uuid=instance.uuid,
reason=msg)

View File

@ -52,7 +52,7 @@ class NovaWebSocketProxy(websockify.WebSocketProxy):
connect_info = rpcapi.check_token(ctxt, token=token)
if not connect_info:
LOG.audit("Invalid Token: %s", token)
LOG.audit(_("Invalid Token: %s"), token)
raise Exception(_("Invalid Token"))
host = connect_info['host']
@ -60,7 +60,8 @@ class NovaWebSocketProxy(websockify.WebSocketProxy):
# Connect to the target
self.msg("connecting to: %s:%s" % (host, port))
LOG.audit("connecting to: %s:%s" % (host, port))
LOG.audit(_("connecting to: %(host)s:%(port)s"),
{'host': host, 'port': port})
tsock = self.socket(host, port, connect=True)
# Handshake as necessary
@ -71,7 +72,7 @@ class NovaWebSocketProxy(websockify.WebSocketProxy):
data = tsock.recv(4096, socket.MSG_PEEK)
if data.find("\r\n\r\n") != -1:
if not data.split("\r\n")[0].find("200"):
LOG.audit("Invalid Connection Info %s", token)
LOG.audit(_("Invalid Connection Info %s"), token)
raise Exception(_("Invalid Connection Info"))
tsock.recv(len(data))
break
@ -87,5 +88,6 @@ class NovaWebSocketProxy(websockify.WebSocketProxy):
tsock.shutdown(socket.SHUT_RDWR)
tsock.close()
self.vmsg("%s:%s: Target closed" % (host, port))
LOG.audit("%s:%s: Target closed" % (host, port))
LOG.audit(_("%(host)s:%(port)s: Target closed"),
{'host': host, 'port': port})
raise

View File

@ -123,7 +123,7 @@ class NovaException(Exception):
# log the issue and the kwargs
LOG.exception(_('Exception in string format operation'))
for name, value in kwargs.iteritems():
LOG.error("%s: %s" % (name, value))
LOG.error("%s: %s" % (name, value)) # noqa
if CONF.fatal_exception_format_errors:
raise exc_info[0], exc_info[1], exc_info[2]

View File

@ -15,6 +15,8 @@
import re
import pep8
"""
Guidelines for writing new hacking checks
@ -50,6 +52,8 @@ asse_equal_end_with_none_re = re.compile(
asse_equal_start_with_none_re = re.compile(
r"(.)*assertEqual\(None, (\w|\.|\'|\"|\[|\])+\)")
conf_attribute_set_re = re.compile(r"CONF\.[a-z0-9_.]+\s*=\s*\w")
log_translation = re.compile(
r"(.)*LOG\.(audit|error|info|warn|warning|critical|exception)\(\s*('|\")")
def import_no_db_in_virt(logical_line, filename):
@ -260,6 +264,19 @@ def no_setting_conf_directly_in_tests(logical_line, filename):
"forbidden. Use self.flags(option=value) instead")
def validate_log_translations(logical_line, physical_line, filename):
# Translations are not required in the test directory
# and the Xen utilities
if ("nova/tests" in filename or
"plugins/xenserver/xenapi/etc/xapi.d" in filename):
return
if pep8.noqa(physical_line):
return
msg = "N321: Log messages require translations!"
if log_translation.match(logical_line):
yield (0, msg)
def factory(register):
register(import_no_db_in_virt)
register(no_db_session_in_public_api)
@ -274,3 +291,4 @@ def factory(register):
register(assert_equal_none)
register(no_translate_debug_logs)
register(no_setting_conf_directly_in_tests)
register(validate_log_translations)

View File

@ -144,3 +144,34 @@ class HackingTestCase(test.NoDBTestCase):
# Shouldn't fail since not in nova/tests/
self.assertEqual(len(list(checks.no_setting_conf_directly_in_tests(
"CONF.option = 1", "nova/compute/foo.py"))), 0)
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'))))

View File

@ -817,8 +817,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver):
class _LibvirtDeprecatedDriver(LibvirtGenericVIFDriver):
def __init__(self, *args, **kwargs):
LOG.warn('VIF driver \"%s\" is marked as deprecated and will be '
'removed in the Juno release.',
LOG.warn(_('VIF driver \"%s\" is marked as deprecated and will be '
'removed in the Juno release.'),
self.__class__.__name__)
super(_LibvirtDeprecatedDriver, self).__init__(*args, **kwargs)