Univention Bugzilla – Bug 51952
Write /var/cache/univention-portal/groups.json atomic to avoid invalid json
Last modified: 2023-01-18 17:21:12 CET
In a customer environment the /var/cache/univention-portal/groups.json file did not contain valid JSON, starting with '{"cn=' and ending with '"someusername",' I guess this was because support had to kill the listener at some point. Stsarting the listener in this state results in a flood of tracebacks: ========================================================================== 07.09.20 15:52:13.304 LISTENER ( ERROR ) : portal_groups: dn='cn=foo123,cn=klassen,cn=schueler,cn=groups,ou=bar,dc=domain,dc=local' command='m' old={'cn': ...} new={'cn': ...} Traceback (most recent call last): File "/usr/lib/python2.7/dist-packages/univention/listener/api_adapter.py", line 147, in _handler self._module_handler.modify(dn, old, new, self._saved_old_dn if self._rename else None) File "/usr/lib/univention-directory-listener/system/portal_groups.py", line 60, in modify groups = self._load() File "/usr/lib/univention-directory-listener/system/portal_groups.py", line 82, in _load return json.load(fd) File "/usr/lib/python2.7/json/__init__.py", line 291, in load **kw) File "/usr/lib/python2.7/json/__init__.py", line 339, in loads return _default_decoder.decode(s) File "/usr/lib/python2.7/json/decoder.py", line 364, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "/usr/lib/python2.7/json/decoder.py", line 380, in raw_decode obj, end = self.scan_once(s, idx) ValueError: Expecting object: line 1 column 2842624 (char 2842623) Traceback (most recent call last): File "/usr/lib/python2.7/dist-packages/univention/listener/api_adapter.py", line 155, in _handler self._module_handler.error_handler(dn, old, new, command, exc_type, exc_value, exc_traceback) File "/usr/lib/python2.7/dist-packages/univention/listener/handler.py", line 243, in error_handler reraise(exc_type, exc_value, exc_traceback) File "/usr/lib/python2.7/dist-packages/univention/listener/api_adapter.py", line 147, in _handler self._module_handler.modify(dn, old, new, self._saved_old_dn if self._rename else None) File "/usr/lib/univention-directory-listener/system/portal_groups.py", line 60, in modify groups = self._load() File "/usr/lib/univention-directory-listener/system/portal_groups.py", line 82, in _load return json.load(fd) File "/usr/lib/python2.7/json/__init__.py", line 291, in load **kw) File "/usr/lib/python2.7/json/__init__.py", line 339, in loads return _default_decoder.decode(s) File "/usr/lib/python2.7/json/decoder.py", line 364, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "/usr/lib/python2.7/json/decoder.py", line 380, in raw_decode obj, end = self.scan_once(s, idx) ValueError: Expecting object: line 1 column 2842624 (char 2842623) 07.09.20 15:37:11.248 LISTENER ( WARN ) : handler: portal_groups (failed) ========================================================================== We should find a more robust (and performant) implementation for this. python-lmdb would be an option.
Created attachment 10471 [details] rebuild-portal-groups Dirk provided a script to reconstruct the file: systemctl stop univention-directory-listener ./rebuild-portal-groups > groups.json ## Inspect file and then chgrp nogroup groups.json mv groups.json /var/cache/univention-portal/groups.json systemctl start univention-directory-listener
This is also a problem in huge environments (customers groups.json > 6Mb) In a customers environment it seems "/var/cache/univention-portal/groups.json" was written by the "portal_groups.py" listener while the portal tried to read the "groups.json". This resulted in an empty portal page. While this case was self healing (you can wait a moment and reload), it is still annoying and created a support case. We should adjust the listener to write the groups cache atomic. Traceback from the portal server: ''' Traceback (most recent call last): File "/usr/lib/python2.7/dist-packages/tornado/web.py", line 1467, in _execute result = method(*self.path_args, **self.path_kwargs) File "/usr/bin/univention-portal-server", line 468, in get portal_content = answer['portal'] = self._get_portal(username, admin_mode) File "/usr/bin/univention-portal-server", line 373, in _get_portal groups = cache.get('groups') File "/usr/bin/univention-portal-server", line 158, in get return self._get_groups() or {} File "/usr/bin/univention-portal-server", line 133, in _get_groups self._groups = json.load(fd) File "/usr/lib/python2.7/json/__init__.py", line 291, in load **kw) File "/usr/lib/python2.7/json/__init__.py", line 339, in loads return _default_decoder.decode(s) File "/usr/lib/python2.7/json/decoder.py", line 364, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "/usr/lib/python2.7/json/decoder.py", line 380, in raw_decode obj, end = self.scan_once(s, idx) ValueError: Unterminated string starting at: line 1 column 5468156 (char 5468155) '''
This is a UCS 4.4 issue. In UCS 5.0, the JSON generation has been reworked and is atomic.