Commit 8eb1881c authored by Jérome Perrin's avatar Jérome Perrin

software/erp5: fix rotation of $ZOPE/var/log/neostorage-0.log

log files used by neo storage are not text files, they are sqlite
databases, so we can not use copytruncate because it leaves a broken
database. For neo, we have to go back to sending a SIGUSR1 signal to
tell neo client to reopen log files. This depends on neo registering
a signal handler, which is done in [1]. It depends on ZServer, so this
approach will probably have to be adjusted when running on python3
because the current plan is that we don't have ZServer installed on
python3.

This depends on a recent erp5.git where runwsgi understands --pidfile
argument.

1: https://lab.nexedi.com/nexedi/neoppod/blob/fd87e153/neo/client/app.py#L58
parent 86721d27
...@@ -179,6 +179,10 @@ class ERP5InstanceTestCase(SlapOSInstanceTestCase, metaclass=ERP5InstanceTestMet ...@@ -179,6 +179,10 @@ class ERP5InstanceTestCase(SlapOSInstanceTestCase, metaclass=ERP5InstanceTestMet
""" """
__test_matrix__ = matrix((zeo, neo)) # switch between NEO and ZEO mode __test_matrix__ = matrix((zeo, neo)) # switch between NEO and ZEO mode
@classmethod
def isNEO(cls):
return '_neo' in cls.__name__
@classmethod @classmethod
def getRootPartitionConnectionParameterDict(cls): def getRootPartitionConnectionParameterDict(cls):
"""Return the output parameters from the root partition""" """Return the output parameters from the root partition"""
......
...@@ -790,6 +790,39 @@ class ZopeTestMixin(ZopeSkinsMixin, CrontabMixin): ...@@ -790,6 +790,39 @@ class ZopeTestMixin(ZopeSkinsMixin, CrontabMixin):
self.assertTrue(os.path.exists(rotated_log_file + '.xz')) self.assertTrue(os.path.exists(rotated_log_file + '.xz'))
self.assertFalse(os.path.exists(rotated_log_file)) self.assertFalse(os.path.exists(rotated_log_file))
def test_neo_root_log_rotation(self):
zope_neo_root_log_path = os.path.join(
self.getComputerPartitionPath('zope-default'),
'var',
'log',
'zope-0-neo-root.log',
)
if not self.isNEO():
self.assertFalse(os.path.exists(zope_neo_root_log_path))
return
def check_sqlite_log(path):
with contextlib.closing(sqlite3.connect(path)) as con:
con.execute('select * from log')
check_sqlite_log(zope_neo_root_log_path)
self._executeCrontabAtDate('logrotate', '2050-01-01')
rotated_log_file = os.path.join(
self.getComputerPartitionPath('zope-default'),
'srv',
'backup',
'logrotate',
'zope-0-neo-root.log-20500101',
)
check_sqlite_log(rotated_log_file)
self._executeCrontabAtDate('logrotate', '2050-01-02')
self.assertTrue(os.path.exists(rotated_log_file + '.xz'))
self.assertFalse(os.path.exists(rotated_log_file))
requests.get(self._getAuthenticatedZopeUrl('/'), verify=False).raise_for_status()
check_sqlite_log(zope_neo_root_log_path)
def test_basic_authentication_user_in_access_log(self): def test_basic_authentication_user_in_access_log(self):
param_dict = self.getRootPartitionConnectionParameterDict() param_dict = self.getRootPartitionConnectionParameterDict()
requests.get(self.zope_base_url, requests.get(self.zope_base_url,
...@@ -867,7 +900,7 @@ class ZopeTestMixin(ZopeSkinsMixin, CrontabMixin): ...@@ -867,7 +900,7 @@ class ZopeTestMixin(ZopeSkinsMixin, CrontabMixin):
'zope-2-Z2.log', 'zope-2-Z2.log',
'zope-2-event.log', 'zope-2-event.log',
'zope-2-neo-root.log', 'zope-2-neo-root.log',
] if '_neo' in self.__class__.__name__ else [ ] if self.isNEO() else [
'zope-0-Z2.log', 'zope-0-Z2.log',
'zope-0-event.log', 'zope-0-event.log',
'zope-1-Z2.log', 'zope-1-Z2.log',
......
...@@ -86,7 +86,7 @@ md5sum = 0ac4b74436f554cd677f19275d18d880 ...@@ -86,7 +86,7 @@ md5sum = 0ac4b74436f554cd677f19275d18d880
[template-zope] [template-zope]
filename = instance-zope.cfg.in filename = instance-zope.cfg.in
md5sum = 558ffbc6d51bb0ce9fc25d1062edcd2a md5sum = e6c94c2a48788683bf0d63d135a44932
[template-balancer] [template-balancer]
filename = instance-balancer.cfg.in filename = instance-balancer.cfg.in
......
...@@ -308,14 +308,14 @@ port = {{ port }} ...@@ -308,14 +308,14 @@ port = {{ port }}
event-log = ${directory:log}/{{ name }}-event.log event-log = ${directory:log}/{{ name }}-event.log
z2-log = ${directory:log}/{{ name }}-Z2.log z2-log = ${directory:log}/{{ name }}-Z2.log
node-id = {{ dumps(node_id_base ~ (node_id_index_format % index)) }} node-id = {{ dumps(node_id_base ~ (node_id_index_format % index)) }}
{% set log_list = [] -%} {% set neo_log_list = [] -%}
{% set import_set = set() -%} {% set import_set = set() -%}
{% for db_name, zodb in six.iteritems(zodb_dict) -%} {% for db_name, zodb in six.iteritems(zodb_dict) -%}
{% do zodb.setdefault('pool-size', thread_amount) -%} {% do zodb.setdefault('pool-size', thread_amount) -%}
{% if zodb['type'] == 'neo' -%} {% if zodb['type'] == 'neo' -%}
{% do import_set.add('neo.client') -%} {% do import_set.add('neo.client') -%}
{% set log = name ~ '-neo-' ~ db_name ~ '.log' -%} {% set log = name ~ '-neo-' ~ db_name ~ '.log' -%}
{% do log_list.append('${directory:log}/' + log) -%} {% do neo_log_list.append('${directory:log}/' + log) -%}
{% do zodb['storage-dict'].update(logfile='~/var/log/'+log) -%} {% do zodb['storage-dict'].update(logfile='~/var/log/'+log) -%}
{% endif -%} {% endif -%}
{% endfor -%} {% endfor -%}
...@@ -350,6 +350,7 @@ wrapped-command-line = ...@@ -350,6 +350,7 @@ wrapped-command-line =
'${:configuration-file}' '${:configuration-file}'
--threads={{ thread_amount }} --threads={{ thread_amount }}
--large-file-threshold={{ slapparameter_dict['large-file-threshold'] }} --large-file-threshold={{ slapparameter_dict['large-file-threshold'] }}
--pidfile={{ '${' ~ conf_parameter_name ~ ':pid-file}' }}
{%- set private_dev_shm = slapparameter_dict['private-dev-shm'] %} {%- set private_dev_shm = slapparameter_dict['private-dev-shm'] %}
{%- if private_dev_shm %} {%- if private_dev_shm %}
private-tmpfs = {{ private_dev_shm }} /dev/shm private-tmpfs = {{ private_dev_shm }} /dev/shm
...@@ -408,8 +409,18 @@ config-maximum-delay = {{ slapparameter_dict["zope-longrequest-logger-maximum-de ...@@ -408,8 +409,18 @@ config-maximum-delay = {{ slapparameter_dict["zope-longrequest-logger-maximum-de
[{{ section('logrotate-entry-' ~ name) }}] [{{ section('logrotate-entry-' ~ name) }}]
< = logrotate-entry-base < = logrotate-entry-base
name = {{ name }} name = {{ name }}
log = {{ '${' ~ conf_parameter_name ~ ':event-log}' }} {{ '${' ~ conf_parameter_name ~ ':z2-log}' }} {{ '${' ~ conf_parameter_name ~ ':longrequest-logger-file}' }} {{ ' '.join(log_list) }} log = {{ '${' ~ conf_parameter_name ~ ':event-log}' }} {{ '${' ~ conf_parameter_name ~ ':z2-log}' }} {{ '${' ~ conf_parameter_name ~ ':longrequest-logger-file}' }}
copytruncate = true copytruncate = true
{% if neo_log_list -%}
[{{ section('logrotate-entry-neo-' ~ name) }}]
< = logrotate-entry-base
name = neo-{{ name }}
log = {{ ' '.join(neo_log_list) }}
# we don't use copytruncate on neo logs, they are not regular text files but sqlite databases
copytruncate =
post = test ! -s {{ '${' ~ conf_parameter_name ~ ':pid-file}' }} || {{ bin_directory }}/slapos-kill --pidfile {{ '${' ~ conf_parameter_name ~ ':pid-file}' }} -s USR2
{% endif %}
{% endmacro -%} {% endmacro -%}
{% for i in instance_index_list -%} {% for i in instance_index_list -%}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment