Add i18n translation for Log messages
Added i18n translation to all log messages. Also added hacking check for this to ensure in future all log messages are translated. Change-Id: I77fbb18ffe47b12232125cc1fa7aae97ea9b1214 Closes-Bug: #1603759
This commit is contained in:
parent
4b66daafd7
commit
fb0057c105
|
@ -19,6 +19,7 @@ from k8sclient.client.apis import apiv_api
|
|||
from oslo_log import log as logging
|
||||
|
||||
from magnum.conductor.handlers.common.cert_manager import create_client_files
|
||||
from magnum.i18n import _LE
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
@ -36,7 +37,7 @@ class K8sAPI(apiv_api.ApivApi):
|
|||
tmp.write(content)
|
||||
tmp.flush()
|
||||
except Exception as err:
|
||||
LOG.error("Error while creating temp file: %s", err)
|
||||
LOG.error(_LE("Error while creating temp file: %s"), err)
|
||||
raise
|
||||
return tmp
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
import re
|
||||
|
||||
import pep8
|
||||
|
||||
"""
|
||||
Guidelines for writing new hacking checks
|
||||
|
||||
|
@ -56,6 +58,14 @@ assert_true_isinstance_re = re.compile(
|
|||
dict_constructor_with_list_copy_re = re.compile(r".*\bdict\((\[)?(\(|\[)")
|
||||
assert_xrange_re = re.compile(
|
||||
r"\s*xrange\s*\(")
|
||||
log_translation = re.compile(
|
||||
r"(.)*LOG\.(audit|error|critical)\(\s*('|\")")
|
||||
log_translation_info = re.compile(
|
||||
r"(.)*LOG\.(info)\(\s*(_\(|'|\")")
|
||||
log_translation_exception = re.compile(
|
||||
r"(.)*LOG\.(exception)\(\s*(_\(|'|\")")
|
||||
log_translation_LW = re.compile(
|
||||
r"(.)*LOG\.(warning|warn)\(\s*(_\(|'|\")")
|
||||
custom_underscore_check = re.compile(r"(.)*_\s*=\s*(.)*")
|
||||
underscore_import_check = re.compile(r"(.)*import _(.)*")
|
||||
translated_log = re.compile(
|
||||
|
@ -125,6 +135,23 @@ def assert_true_isinstance(logical_line):
|
|||
yield (0, "M316: assertTrue(isinstance(a, b)) sentences not allowed")
|
||||
|
||||
|
||||
def validate_log_translations(logical_line, physical_line, filename=None):
|
||||
if pep8.noqa(physical_line):
|
||||
return
|
||||
msg = "M328: LOG.info messages require translations `_LI()`!"
|
||||
if log_translation_info.match(logical_line):
|
||||
yield (0, msg)
|
||||
msg = "M329: LOG.exception messages require translations `_LE()`!"
|
||||
if log_translation_exception.match(logical_line):
|
||||
yield (0, msg)
|
||||
msg = "M330: LOG.warning, LOG.warn messages require translations `_LW()`!"
|
||||
if log_translation_LW.match(logical_line):
|
||||
yield (0, msg)
|
||||
msg = "M321: Log messages require translations!"
|
||||
if log_translation.match(logical_line):
|
||||
yield (0, msg)
|
||||
|
||||
|
||||
def assert_equal_in(logical_line):
|
||||
"""Check for assertEqual(True|False, A in B), assertEqual(A in B, True|False)
|
||||
|
||||
|
@ -215,4 +242,5 @@ def factory(register):
|
|||
register(dict_constructor_with_list_copy)
|
||||
register(no_xrange)
|
||||
register(no_log_warn)
|
||||
register(validate_log_translations)
|
||||
register(check_explicit_underscore_import)
|
||||
|
|
|
@ -132,9 +132,10 @@ class MagnumPeriodicTasks(periodic_task.PeriodicTasks):
|
|||
# Any other exception means we do not perform any
|
||||
# action on this bay in the current sync run, so remove
|
||||
# it from all records.
|
||||
LOG.warning("Exception while attempting to retrieve "
|
||||
"Heat stack %s for bay %s. Traceback "
|
||||
"follows.")
|
||||
LOG.warning(_LW("Exception while attempting to retrieve "
|
||||
"Heat stack %(stack_id)s for bay %(bay_id)s. "
|
||||
"Traceback follows."),
|
||||
{'stack_id': bay.stack_id, 'bay_id': bay.id})
|
||||
LOG.warning(e)
|
||||
_sid_to_bay_mapping.pop(bay.stack_id)
|
||||
_bay_stack_ids.remove(bay.stack_id)
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
from oslo_log import log as logging
|
||||
from tempest.lib import exceptions
|
||||
|
||||
from magnum.i18n import _LE
|
||||
from magnum.i18n import _LI
|
||||
from magnum.i18n import _LW
|
||||
from magnum.tests.functional.api.v1.models import bay_model
|
||||
from magnum.tests.functional.common import client
|
||||
from magnum.tests.functional.common import utils
|
||||
|
@ -120,9 +123,9 @@ class BayClient(client.MagnumClient):
|
|||
lambda: self.does_bay_exist(bay_id), 10, 1800)
|
||||
except Exception:
|
||||
# In error state. Clean up the bay id if desired
|
||||
self.LOG.error('Bay %s entered an exception state.' % bay_id)
|
||||
self.LOG.error(_LE('Bay %s entered an exception state.') % bay_id)
|
||||
if delete_on_error:
|
||||
self.LOG.error('We will attempt to delete bays now.')
|
||||
self.LOG.error(_LE('We will attempt to delete bays now.'))
|
||||
self.delete_bay(bay_id)
|
||||
self.wait_for_bay_to_delete(bay_id)
|
||||
raise
|
||||
|
@ -136,35 +139,35 @@ class BayClient(client.MagnumClient):
|
|||
resp, model = self.get_bay(bay_id)
|
||||
if model.status in ['CREATED', 'CREATE_COMPLETE',
|
||||
'ERROR', 'CREATE_FAILED']:
|
||||
self.LOG.info('Bay %s succeeded.' % bay_id)
|
||||
self.LOG.info(_LI('Bay %s succeeded.') % bay_id)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
except exceptions.NotFound:
|
||||
self.LOG.warning('Bay %s is not found.' % bay_id)
|
||||
self.LOG.warning(_LW('Bay %s is not found.') % bay_id)
|
||||
return False
|
||||
|
||||
def does_bay_exist(self, bay_id):
|
||||
try:
|
||||
resp, model = self.get_bay(bay_id)
|
||||
if model.status in ['CREATED', 'CREATE_COMPLETE']:
|
||||
self.LOG.info('Bay %s is created.' % bay_id)
|
||||
self.LOG.info(_LI('Bay %s is created.') % bay_id)
|
||||
return True
|
||||
elif model.status in ['ERROR', 'CREATE_FAILED']:
|
||||
self.LOG.error('Bay %s is in fail state.' % bay_id)
|
||||
self.LOG.error(_LE('Bay %s is in fail state.') % bay_id)
|
||||
raise exceptions.ServerFault(
|
||||
"Got into an error condition: %s for %s" %
|
||||
(model.status, bay_id))
|
||||
else:
|
||||
return False
|
||||
except exceptions.NotFound:
|
||||
self.LOG.warning('Bay %s is not found.' % bay_id)
|
||||
self.LOG.warning(_LW('Bay %s is not found.') % bay_id)
|
||||
return False
|
||||
|
||||
def does_bay_not_exist(self, bay_id):
|
||||
try:
|
||||
self.get_bay(bay_id)
|
||||
except exceptions.NotFound:
|
||||
self.LOG.warning('Bay %s is not found.' % bay_id)
|
||||
self.LOG.warning(_LW('Bay %s is not found.') % bay_id)
|
||||
return True
|
||||
return False
|
||||
|
|
|
@ -17,6 +17,8 @@ import subprocess
|
|||
from tempest.lib import base
|
||||
|
||||
import magnum
|
||||
from magnum.i18n import _LE
|
||||
from magnum.i18n import _LI
|
||||
|
||||
|
||||
COPY_LOG_HELPER = "magnum/tests/contrib/copy_instance_logs.sh"
|
||||
|
@ -44,10 +46,10 @@ class BaseMagnumTest(base.BaseTestCase):
|
|||
"""
|
||||
def int_copy_logs(exec_info):
|
||||
try:
|
||||
cls.LOG.info("Copying logs...")
|
||||
cls.LOG.info(_LI("Copying logs..."))
|
||||
fn = exec_info[2].tb_frame.f_locals['fn']
|
||||
func_name = fn.im_self._get_test_method().__name__
|
||||
msg = "Failed to copy logs for bay"
|
||||
msg = (_LE("Failed to copy logs for bay"))
|
||||
nodes_addresses = get_nodes_fn()
|
||||
|
||||
master_nodes = nodes_addresses[0]
|
||||
|
@ -61,8 +63,8 @@ class BaseMagnumTest(base.BaseTestCase):
|
|||
if not nodes_address:
|
||||
return
|
||||
|
||||
cls.LOG.info("copy logs from : %s" %
|
||||
','.join(nodes_address))
|
||||
msg = _LI("copy logs from : %s") % ','.join(nodes_address)
|
||||
cls.LOG.info(msg)
|
||||
log_name = prefix + "-" + func_name
|
||||
for node_address in nodes_address:
|
||||
try:
|
||||
|
@ -77,10 +79,13 @@ class BaseMagnumTest(base.BaseTestCase):
|
|||
])
|
||||
except Exception:
|
||||
cls.LOG.error(msg)
|
||||
cls.LOG.exception(
|
||||
"failed to copy from %s to %s%s-%s" %
|
||||
(node_address, "/opt/stack/logs/bay-nodes/",
|
||||
log_name, node_address))
|
||||
msg = (_LE("failed to copy from %{node_address}s "
|
||||
"to %{base_path}s%{log_name}s-"
|
||||
"%{node_address}s") %
|
||||
{'node_address': node_address,
|
||||
'base_path': "/opt/stack/logs/bay-nodes/",
|
||||
'log_name': log_name})
|
||||
cls.LOG.exception(msg)
|
||||
|
||||
do_copy_logs('master', master_nodes)
|
||||
do_copy_logs('node', agent_nodes)
|
||||
|
|
|
@ -31,6 +31,7 @@ from k8sclient.client import api_client
|
|||
from k8sclient.client.apis import apiv_api
|
||||
from keystoneclient.v2_0 import client as ksclient
|
||||
from magnum.common.utils import rmtree_without_raise
|
||||
from magnum.i18n import _LI
|
||||
from magnum.tests.functional.common import base
|
||||
from magnum.tests.functional.common import utils
|
||||
from magnumclient.common.apiclient import exceptions
|
||||
|
@ -275,11 +276,11 @@ extendedKeyUsage = clientAuth
|
|||
def _get_nodes(self):
|
||||
nodes = self._get_nodes_from_bay()
|
||||
if not [x for x in nodes if x]:
|
||||
self.LOG.info("the list of nodes from bay is empty")
|
||||
self.LOG.info(_LI("the list of nodes from bay is empty"))
|
||||
nodes = self._get_nodes_from_stack()
|
||||
if not [x for x in nodes if x]:
|
||||
self.LOG.info("the list of nodes from stack is empty")
|
||||
self.LOG.info("Nodes are: %s" % nodes)
|
||||
self.LOG.info(_LI("the list of nodes from stack is empty"))
|
||||
self.LOG.info(_LI("Nodes are: %s") % nodes)
|
||||
return nodes
|
||||
|
||||
def _get_nodes_from_bay(self):
|
||||
|
@ -378,10 +379,10 @@ class BaseK8sTest(BayTest):
|
|||
def _is_api_ready(self):
|
||||
try:
|
||||
self.k8s_api.list_namespaced_node()
|
||||
self.LOG.info("API is ready.")
|
||||
self.LOG.info(_LI("API is ready."))
|
||||
return True
|
||||
except Exception:
|
||||
self.LOG.info("API is not ready yet.")
|
||||
self.LOG.info(_LI("API is not ready yet."))
|
||||
return False
|
||||
|
||||
def test_pod_apis(self):
|
||||
|
|
|
@ -17,6 +17,7 @@ from oslo_config import cfg
|
|||
from requests import exceptions as req_exceptions
|
||||
|
||||
from magnum.common import docker_utils
|
||||
from magnum.i18n import _LI
|
||||
from magnum.tests.functional.python_client_base import BayTest
|
||||
|
||||
|
||||
|
@ -97,15 +98,15 @@ class TestSwarmAPIs(BayTest):
|
|||
# investigate the cause of this issue. See bug #1583337.
|
||||
for i in range(150):
|
||||
try:
|
||||
self.LOG.info("Calling function " + func.__name__)
|
||||
self.LOG.info(_LI("Calling function ") + func.__name__)
|
||||
return func(*args, **kwargs)
|
||||
except req_exceptions.ConnectionError:
|
||||
self.LOG.info("Connection aborted on calling Swarm API. "
|
||||
"Will retry in 2 seconds.")
|
||||
self.LOG.info(_LI("Connection aborted on calling Swarm API. "
|
||||
"Will retry in 2 seconds."))
|
||||
except errors.APIError as e:
|
||||
if e.response.status_code != 500:
|
||||
raise
|
||||
self.LOG.info("Internal Server Error: " + str(e))
|
||||
self.LOG.info(_LI("Internal Server Error: ") + str(e))
|
||||
time.sleep(2)
|
||||
|
||||
raise Exception("Cannot connect to Swarm API.")
|
||||
|
|
|
@ -215,6 +215,28 @@ class HackingTestCase(base.TestCase):
|
|||
"""
|
||||
self._assert_has_no_errors(code, check)
|
||||
|
||||
def test_log_translations(self):
|
||||
logs = ['audit', 'error', 'info', 'warning', 'critical', 'warn',
|
||||
'exception']
|
||||
levels = ['_LI', '_LW', '_LE', '_LC']
|
||||
debug = "LOG.debug('OK')"
|
||||
self.assertEqual(
|
||||
0, len(list(checks.validate_log_translations(debug, debug))))
|
||||
for log in logs:
|
||||
bad = 'LOG.%s("Bad")' % log
|
||||
self.assertEqual(
|
||||
1, len(list(checks.validate_log_translations(bad, bad))))
|
||||
ok = "LOG.%s('OK') # noqa" % log
|
||||
self.assertEqual(
|
||||
0, len(list(checks.validate_log_translations(ok, ok))))
|
||||
ok = "LOG.%s(variable)" % log
|
||||
self.assertEqual(
|
||||
0, len(list(checks.validate_log_translations(ok, ok))))
|
||||
for level in levels:
|
||||
ok = "LOG.%s(%s('OK'))" % (log, level)
|
||||
self.assertEqual(
|
||||
0, len(list(checks.validate_log_translations(ok, ok))))
|
||||
|
||||
def test_use_timeunitls_utcow(self):
|
||||
errors = [(1, 0, "M310")]
|
||||
check = checks.use_timeutils_utcnow
|
||||
|
|
Loading…
Reference in New Issue