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.