From c98d3f479b7ef7f6ad6fce8aa3633f27eed41c2b Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Fri, 1 Jul 2016 13:51:05 +0200 Subject: [PATCH] Allow customizing ramdisk logs file names and simplify the default The template for ramdisk logs file names can now be changed via the configuration. The default now contains only node UUID and datetime. Also a proper tar.gz extension is appended to avoid confusion. Depends-On: Ie507e2e5c58cffa255bbfb2fa5ffb95cb98ed8c4 Change-Id: I738f9bd35705d0d11c95b0164186ed0b366b5252 --- example.conf | 102 +++++++++--------- ironic_inspector/conf.py | 8 ++ ironic_inspector/process.py | 15 ++- ironic_inspector/test/unit/test_process.py | 20 +++- ...tom-ramdisk-log-name-dac06822c38657e7.yaml | 8 ++ 5 files changed, 96 insertions(+), 57 deletions(-) create mode 100644 releasenotes/notes/custom-ramdisk-log-name-dac06822c38657e7.yaml diff --git a/example.conf b/example.conf index 64c8037fa..6132eb4be 100644 --- a/example.conf +++ b/example.conf @@ -408,15 +408,15 @@ # From ironic_inspector.common.ironic # -# Authentication URL (unknown value) +# Authentication URL (string value) #auth_url = # Method to use for authentication: noauth or keystone. (string value) # Allowed values: keystone, noauth #auth_strategy = keystone -# Authentication type to load (unknown value) -# Deprecated group/name - [DEFAULT]/auth_plugin +# Authentication type to load (string value) +# Deprecated group/name - [ironic]/auth_plugin #auth_type = # PEM encoded Certificate Authority to use when verifying HTTPs @@ -428,18 +428,18 @@ # Optional domain ID to use with v3 and v2 parameters. It will be used # for both the user and project domain in v3 and ignored in v2 -# authentication. (unknown value) +# authentication. (string value) #default_domain_id = # Optional domain name to use with v3 API and v2 parameters. It will # be used for both the user and project domain in v3 and ignored in v2 -# authentication. (unknown value) +# authentication. (string value) #default_domain_name = -# Domain ID to scope to (unknown value) +# Domain ID to scope to (string value) #domain_id = -# Domain name to scope to (unknown value) +# Domain name to scope to (string value) #domain_name = # DEPRECATED: Keystone admin endpoint. DEPRECATED: Use @@ -510,50 +510,50 @@ # Reason: Use options presented by configured keystone auth plugin. #os_username = -# User's password (unknown value) +# User's password (string value) #password = -# Domain ID containing project (unknown value) +# Domain ID containing project (string value) #project_domain_id = -# Domain name containing project (unknown value) +# Domain name containing project (string value) #project_domain_name = -# Project ID to scope to (unknown value) -# Deprecated group/name - [DEFAULT]/tenant-id +# Project ID to scope to (string value) +# Deprecated group/name - [ironic]/tenant-id #project_id = -# Project name to scope to (unknown value) -# Deprecated group/name - [DEFAULT]/tenant-name +# Project name to scope to (string value) +# Deprecated group/name - [ironic]/tenant-name #project_name = # Interval between retries in case of conflict error (HTTP 409). # (integer value) #retry_interval = 2 -# Tenant ID (unknown value) +# Tenant ID (string value) #tenant_id = -# Tenant Name (unknown value) +# Tenant Name (string value) #tenant_name = # Timeout value for http requests (integer value) #timeout = -# Trust ID (unknown value) +# Trust ID (string value) #trust_id = -# User's domain id (unknown value) +# User's domain id (string value) #user_domain_id = -# User's domain name (unknown value) +# User's domain name (string value) #user_domain_name = -# User id (unknown value) +# User id (string value) #user_id = -# Username (unknown value) -# Deprecated group/name - [DEFAULT]/user-name +# Username (string value) +# Deprecated group/name - [ironic]/user-name #username = @@ -609,7 +609,7 @@ # Optionally specify a list of memcached server(s) to use for caching. # If left undefined, tokens will instead be cached in-process. (list # value) -# Deprecated group/name - [DEFAULT]/memcache_servers +# Deprecated group/name - [keystone_authtoken]/memcache_servers #memcached_servers = # In order to prevent excessive effort spent validating tokens, the @@ -693,11 +693,11 @@ # value) #hash_algorithms = md5 -# Authentication type to load (unknown value) -# Deprecated group/name - [DEFAULT]/auth_plugin +# Authentication type to load (string value) +# Deprecated group/name - [keystone_authtoken]/auth_plugin #auth_type = -# Config Section from which to load plugin specific options (unknown +# Config Section from which to load plugin specific options (string # value) #auth_section = @@ -785,6 +785,12 @@ # processing. (boolean value) #log_bmc_address = true +# File name template for storing ramdisk logs. The following +# replacements can be used: {uuid} - node UUID or "unknown", {bmc} - +# node BMC address or "unknown", {dt} - current UTC date and time, +# {mac} - PXE booting MAC or "unknown". (string value) +#ramdisk_logs_filename_format = {uuid}_bmc_{bmc}-{dt:%Y.%m.%d_%H.%M.%S_%f}.tar.gz + [swift] @@ -792,11 +798,11 @@ # From ironic_inspector.common.swift # -# Authentication URL (unknown value) +# Authentication URL (string value) #auth_url = -# Authentication type to load (unknown value) -# Deprecated group/name - [DEFAULT]/auth_plugin +# Authentication type to load (string value) +# Deprecated group/name - [swift]/auth_plugin #auth_type = # PEM encoded Certificate Authority to use when verifying HTTPs @@ -811,22 +817,22 @@ # Optional domain ID to use with v3 and v2 parameters. It will be used # for both the user and project domain in v3 and ignored in v2 -# authentication. (unknown value) +# authentication. (string value) #default_domain_id = # Optional domain name to use with v3 API and v2 parameters. It will # be used for both the user and project domain in v3 and ignored in v2 -# authentication. (unknown value) +# authentication. (string value) #default_domain_name = # Number of seconds that the Swift object will last before being # deleted. (set to 0 to never delete the object). (integer value) #delete_after = 0 -# Domain ID to scope to (unknown value) +# Domain ID to scope to (string value) #domain_id = -# Domain name to scope to (unknown value) +# Domain name to scope to (string value) #domain_name = # Verify HTTPS connections. (boolean value) @@ -860,44 +866,44 @@ # Swift service type. (string value) #os_service_type = object-store -# User's password (unknown value) +# User's password (string value) #password = -# Domain ID containing project (unknown value) +# Domain ID containing project (string value) #project_domain_id = -# Domain name containing project (unknown value) +# Domain name containing project (string value) #project_domain_name = -# Project ID to scope to (unknown value) -# Deprecated group/name - [DEFAULT]/tenant-id +# Project ID to scope to (string value) +# Deprecated group/name - [swift]/tenant-id #project_id = -# Project name to scope to (unknown value) -# Deprecated group/name - [DEFAULT]/tenant-name +# Project name to scope to (string value) +# Deprecated group/name - [swift]/tenant-name #project_name = -# Tenant ID (unknown value) +# Tenant ID (string value) #tenant_id = -# Tenant Name (unknown value) +# Tenant Name (string value) #tenant_name = # Timeout value for http requests (integer value) #timeout = -# Trust ID (unknown value) +# Trust ID (string value) #trust_id = -# User's domain id (unknown value) +# User's domain id (string value) #user_domain_id = -# User's domain name (unknown value) +# User's domain name (string value) #user_domain_name = -# User id (unknown value) +# User id (string value) #user_id = -# Username (unknown value) -# Deprecated group/name - [DEFAULT]/user-name +# Username (string value) +# Deprecated group/name - [swift]/user-name #username = diff --git a/ironic_inspector/conf.py b/ironic_inspector/conf.py index 8f8748a79..ecb74af13 100644 --- a/ironic_inspector/conf.py +++ b/ironic_inspector/conf.py @@ -129,6 +129,14 @@ PROCESSING_OPTS = [ default=True, help='Whether to log node BMC address with every message ' 'during processing.'), + cfg.StrOpt('ramdisk_logs_filename_format', + default='{uuid}_{dt:%Y%m%d-%H%M%S.%f}.tar.gz', + help='File name template for storing ramdisk logs. The ' + 'following replacements can be used: ' + '{uuid} - node UUID or "unknown", ' + '{bmc} - node BMC address or "unknown", ' + '{dt} - current UTC date and time, ' + '{mac} - PXE booting MAC or "unknown".'), ] diff --git a/ironic_inspector/process.py b/ironic_inspector/process.py index 83b7ddccd..674a055f2 100644 --- a/ironic_inspector/process.py +++ b/ironic_inspector/process.py @@ -41,7 +41,6 @@ _CREDENTIALS_WAIT_RETRIES = 10 _CREDENTIALS_WAIT_PERIOD = 3 _STORAGE_EXCLUDED_KEYS = {'logs'} _UNPROCESSED_DATA_STORE_SUFFIX = 'UNPROCESSED' -_DATETIME_FORMAT = '%Y.%m.%d_%H.%M.%S_%f' def _store_logs(introspection_data, node_info): @@ -58,10 +57,16 @@ def _store_logs(introspection_data, node_info): data=introspection_data, node_info=node_info) return - time_fmt = datetime.datetime.utcnow().strftime(_DATETIME_FORMAT) - bmc_address = (utils.get_ipmi_address_from_data(introspection_data) - or 'unknown') - file_name = 'bmc_%s_%s' % (bmc_address, time_fmt) + fmt_args = { + 'uuid': node_info.uuid if node_info is not None else 'unknown', + 'mac': (utils.get_pxe_mac(introspection_data) or + 'unknown').replace(':', ''), + 'dt': datetime.datetime.utcnow(), + 'bmc': (utils.get_ipmi_address_from_data(introspection_data) or + 'unknown') + } + + file_name = CONF.processing.ramdisk_logs_filename_format.format(**fmt_args) try: if not os.path.exists(CONF.processing.ramdisk_logs_dir): diff --git a/ironic_inspector/test/unit/test_process.py b/ironic_inspector/test/unit/test_process.py index befc4ed01..3a8163132 100644 --- a/ironic_inspector/test/unit/test_process.py +++ b/ironic_inspector/test/unit/test_process.py @@ -258,13 +258,15 @@ class TestStoreLogs(BaseProcessTest): self.logs = b'test logs' self.data['logs'] = base64.b64encode(self.logs) - def _check_contents(self): + def _check_contents(self, name=None): files = os.listdir(self.tempdir) self.assertEqual(1, len(files)) filename = files[0] - self.assertTrue(filename.startswith('bmc_%s_' % self.bmc_address), - '%s does not start with bmc_%s' - % (filename, self.bmc_address)) + if name is None: + self.assertTrue(filename.startswith(self.uuid), + '%s does not start with uuid' % filename) + else: + self.assertEqual(name, filename) with open(os.path.join(self.tempdir, filename), 'rb') as fp: self.assertEqual(self.logs, fp.read()) @@ -323,6 +325,16 @@ class TestStoreLogs(BaseProcessTest): self.assertRaises(utils.Error, process.process, self.data) self._check_contents() + def test_store_custom_name(self, hook_mock): + CONF.set_override('ramdisk_logs_filename_format', + '{uuid}-{bmc}-{mac}', + 'processing') + self.process_mock.side_effect = utils.Error('boom') + self.assertRaises(utils.Error, process.process, self.data) + self._check_contents(name='%s-%s-%s' % (self.uuid, + self.bmc_address, + self.pxe_mac.replace(':', ''))) + class TestProcessNode(BaseTest): def setUp(self): diff --git a/releasenotes/notes/custom-ramdisk-log-name-dac06822c38657e7.yaml b/releasenotes/notes/custom-ramdisk-log-name-dac06822c38657e7.yaml new file mode 100644 index 000000000..ff15bad38 --- /dev/null +++ b/releasenotes/notes/custom-ramdisk-log-name-dac06822c38657e7.yaml @@ -0,0 +1,8 @@ +--- +features: + - File name for stored ramdisk logs can now be customized via + "ramdisk_logs_filename_format" option. +upgrade: + - The default file name for stored ramdisk logs was change to contain only + node UUID (if known) and the current date time. A proper ".tar.gz" + extension is now appended.