Commit fb661595 authored by Jérome Perrin's avatar Jérome Perrin

stack/erp5: fix ZEO repozo backups not produced on python3

Products.TIDStorage was not ported to python3 and is not installed on
software-py3.cfg but the backup crontab expects tidstorage to be
present - as a result, it was silently failing to produce backups.

This brings minimal support to repozo backups on python3, without
Products.TIDStorage interraction and also extends software release test
to have a simple test checking that backups are produced and can be
restored.
parent 95b5d1a4
......@@ -51,6 +51,8 @@ setup(name=name,
'cryptography',
'pexpect',
'pyOpenSSL',
'ZEO',
'zodburi',
],
test_suite='test',
)
import contextlib
import subprocess
import json
import zodburi
from ZODB.DB import DB
from slapos.testing.utils import CrontabMixin
from . import ERP5InstanceTestCase, default, matrix, setUpModule, ERP5PY3
_ = setUpModule
class ZEOTestCase(ERP5InstanceTestCase):
__test_matrix__ = matrix((default,))
@classmethod
def getInstanceSoftwareType(cls) -> str:
return "zodb-zeo"
@classmethod
def _getInstanceParameterDict(cls) -> dict:
return {
"tcpv4-port": 8000,
"computer-memory-percent-threshold": 100,
"name": cls.__name__,
"monitor-passwd": "secret",
"zodb-dict": {"root": {}},
}
@classmethod
def getInstanceParameterDict(cls) -> dict:
return {"_": json.dumps(cls._getInstanceParameterDict())}
def setUp(self) -> None:
self.storage_dict = json.loads(
self.computer_partition.getConnectionParameterDict()["_"]
)["storage-dict"]
def db(self) -> contextlib.AbstractContextManager[DB]:
root = self.storage_dict["root"]
zeo_uri = f"zeo://{root['server']}?storage={root['storage']}"
storage_factory, dbkw = zodburi.resolve_uri(zeo_uri)
return contextlib.closing(DB(storage_factory(), **dbkw))
class TestRepozo(ZEOTestCase, CrontabMixin):
__partition_reference__ = "rpz"
def test_backup_and_restore(self) -> None:
def check_state():
(self.computer_partition_root_path / ".timestamp").unlink()
self.waitForInstance()
if ERP5PY3:
with self.db() as db:
with db.transaction() as cnx:
self.assertEqual(cnx.root.state, "before backup")
if ERP5PY3:
# as it is not possible to connect to a python2 ZEO server
# from a python3 client, we check more when the server is python3
with self.db() as db:
with db.transaction() as cnx:
cnx.root.state = "before backup"
check_state()
self._executeCrontabAtDate("tidstorage", "2000-01-01 UTC")
dat, fsz, index = sorted(
[
p.name
for p in (
self.computer_partition_root_path / "srv" / "backup" / "zodb" / "root"
).glob("*")
]
)
self.assertRegexpMatches(dat, r'2000-01-01-00-\d\d-\d\d.dat')
self.assertRegexpMatches(fsz, r'2000-01-01-00-\d\d-\d\d.fsz')
self.assertRegexpMatches(index, r'2000-01-01-00-\d\d-\d\d.index')
if ERP5PY3:
with self.db() as db:
with db.transaction() as cnx:
cnx.root.state = "after backup"
db.close()
restore_script = self.computer_partition_root_path / "srv" / "runner-import-restore"
self.assertTrue(restore_script.exists())
status, restore_output = subprocess.getstatusoutput(str(restore_script))
self.assertEqual(status, 1)
self.assertIn("Zeo is already running", restore_output)
with self.slap.instance_supervisor_rpc as supervisor:
supervisor.stopAllProcesses()
restore_output = subprocess.check_output(restore_script)
check_state()
......@@ -14,6 +14,7 @@ extends =
../../component/python-pynacl/buildout.cfg
../../component/python-backports-lzma/buildout.cfg
../../component/selenium/buildout.cfg
../../component/ZODB/buildout.cfg
../../stack/slapos.cfg
../../stack/nxdtest.cfg
......@@ -356,6 +357,7 @@ setup = ${recurls-repository:location}
[python-interpreter]
eggs +=
${BTrees:egg}
${lxml-python:egg}
${python-PyYAML:egg}
${slapos.core-setup:egg}
......@@ -365,6 +367,7 @@ eggs +=
beautifulsoup4
caucase
erp5.util
${persistent:egg}
${python-pynacl:egg}
${python-cryptography:egg}
${python-mysqlclient:egg}
......@@ -526,15 +529,23 @@ recurls =
slapos.core =
# Various needed versions
Pillow = 10.2.0+SlapOSPatched001
BTrees = 6.1
forcediphttpsadapter = 1.0.1
image = 1.5.25
mysqlclient = 2.1.1
paho-mqtt = 1.5.0
pcpp = 1.30
persistent = 6.1
Pillow = 10.2.0+SlapOSPatched001
plantuml = 0.3.0:whl
pypdf = 3.6.0:whl
pysftp = 0.2.9
requests-toolbelt = 0.8.0
testfixtures = 6.11.0
mysqlclient = 2.1.1
paho-mqtt = 1.5.0
pcpp = 1.30
transaction = 5.0
xmltodict = 0.13.0
ZEO = 6.0.0
ZODB = 6.0.0
zodbpickle = 4.1.1
zope.deferredimport = 5.0
zope.proxy = 6.1
......@@ -78,7 +78,7 @@ md5sum = 1333d2fc21f64da4010a4eafea59d141
[template-zeo]
filename = instance-zeo.cfg.in
md5sum = 218ffa7beb27693670664f64b993ed44
md5sum = 33075c3ab06613874b928d90e0c0006a
[template-zeo-conf]
filename = zeo.conf.in
......
......@@ -80,6 +80,44 @@ config-port = {{ "${" ~ zeo_section_name ~ ":port}" }}
{% set tidstorage_repozo_path = '' -%}
{% else -%}
[repozo-backup-script]
repozo-wrapper = ${buildout:bin-directory}/tidstorage-repozo
# BBB on python3 we don't use Products.TIDStorage but repozo directly.
[repozo-backup-script:python3]
recipe = slapos.recipe.template
inline =
#!/bin/sh
zodb_directory="${directory:zodb}"
zodb_backup_directory="{{ default_backup_path }}"
repozo="${tidstorage:repozo-binary}"
EXIT_CODE=0
{% for family, zodb in six.iteritems(zodb_dict) -%}
{% for name, zodb in zodb -%}
storage_name="{{ name }}"
zodb_path="$storage_name.fs"
[ ! -d "$zodb_backup_directory/$storage_name" ]] && mkdir "$zodb_backup_directory/$storage_name"
echo "Backing up $storage_name ..."
$repozo \
--backup \
--gzip \
--quick \
--repository="$zodb_backup_directory/$storage_name" \
--file="$zodb_directory/$zodb_path"
CURRENT_EXIT_CODE=$?
if [ ! "$CURRENT_EXIT_CODE"="0" ]; then
EXIT_CODE="$CURRENT_EXIT_CODE"
echo "$storage_name Backup restoration failed."
fi
{% endfor -%}
{% endfor -%}
exit $EXIT_CODE
repozo-wrapper = ${:output}
mode = 755
output = ${buildout:bin-directory}/repozo-backup
[tidstorage]
recipe = slapos.cookbook:tidstorage
known-tid-storage-identifier-dict = {{ dumps(known_tid_storage_identifier_dict) }}
......@@ -116,7 +154,7 @@ recipe = slapos.cookbook:cron.d
cron-entries = ${cron:cron-entries}
name = tidstorage
time = {{ dumps(backup_periodicity) }}
command = ${tidstorage:repozo-wrapper}
command = ${repozo-backup-script:repozo-wrapper}
# Used for ERP5 resiliency or (more probably)
# webrunner resiliency with erp5 inside.
......
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