diff --git a/ironic/common/utils.py b/ironic/common/utils.py index a257531069..e15083396c 100644 --- a/ironic/common/utils.py +++ b/ironic/common/utils.py @@ -18,6 +18,7 @@ """Utilities and helper functions.""" +from collections import abc import contextlib import datetime import errno @@ -638,3 +639,18 @@ def is_memory_insufficent(raise_if_fail=False): # Sleep so interpreter can switch threads. time.sleep(CONF.minimum_memory_wait_time) loop_count = loop_count + 1 + + +_LARGE_KEYS = frozenset(['system_logs']) + + +def remove_large_keys(var): + """Remove specific keys from the var, recursing into dicts and lists.""" + if isinstance(var, abc.Mapping): + return {key: (remove_large_keys(value) + if key not in _LARGE_KEYS else '<...>') + for key, value in var.items()} + elif isinstance(var, abc.Sequence) and not isinstance(var, str): + return var.__class__(map(remove_large_keys, var)) + else: + return var diff --git a/ironic/drivers/modules/agent_client.py b/ironic/drivers/modules/agent_client.py index 8d1318b8e4..7b2059ee22 100644 --- a/ironic/drivers/modules/agent_client.py +++ b/ironic/drivers/modules/agent_client.py @@ -24,6 +24,7 @@ import tenacity from ironic.common import exception from ironic.common.i18n import _ +from ironic.common import utils from ironic.conf import CONF LOG = log.getLogger(__name__) @@ -53,6 +54,15 @@ def get_command_error(command): return error +def _sanitize_for_logging(var): + if not var: + return var + elif isinstance(var, str): + return strutils.mask_password(var) + else: + return utils.remove_large_keys(strutils.mask_dict_password(var)) + + class AgentClient(object): """Client for interacting with nodes via a REST API.""" @METRICS.timer('AgentClient.__init__') @@ -170,8 +180,10 @@ class AgentClient(object): agent_token = node.driver_internal_info.get('agent_secret_token') if agent_token: request_params['agent_token'] = agent_token - LOG.debug('Executing agent command %(method)s for node %(node)s', - {'node': node.uuid, 'method': method}) + LOG.debug('Executing agent command %(method)s for node %(node)s ' + 'with params %(params)s', + {'node': node.uuid, 'method': method, + 'params': _sanitize_for_logging(request_params)}) try: response = self.session.post( @@ -208,7 +220,7 @@ class AgentClient(object): LOG.debug('Agent command %(method)s for node %(node)s returned ' 'result %(res)s, error %(error)s, HTTP status code %(code)s', {'node': node.uuid, 'method': method, - 'res': result.get('command_result'), + 'res': _sanitize_for_logging(result.get('command_result')), 'error': error, 'code': response.status_code if response is not None else 'unknown'}) @@ -313,7 +325,8 @@ class AgentClient(object): result = _get().json()['commands'] status = '; '.join('%(cmd)s: result "%(res)s", error "%(err)s"' % {'cmd': r.get('command_name'), - 'res': r.get('command_result'), + 'res': _sanitize_for_logging( + r.get('command_result')), 'err': r.get('command_error')} for r in result) LOG.debug('Status of agent commands for node %(node)s: %(status)s',