Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DPE-2119] fix issues and tests when reusing storage #272

Merged
merged 137 commits into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
137 commits
Select commit Hold shift + click to select a range
1227daf
update revision number of installed snap (fixes installation issue w…
reneradoi Apr 30, 2024
e149fbb
test_storage.py: add storage pool, deploy model with persistent stora…
reneradoi Apr 30, 2024
069441a
test_storage.py: adjust testing workflow, deploy 2 units and scale do…
reneradoi Apr 30, 2024
ea43e97
test_storage.py: app status will not be active because after scaling …
reneradoi Apr 30, 2024
5ad2aa8
test_storage.py: force-destroy the application when removing the cluster
reneradoi Apr 30, 2024
f82d403
test_storage.py: fix comment
reneradoi Apr 30, 2024
58d6e36
test_storage.py: formatting
reneradoi Apr 30, 2024
ecb86b0
test_storage.py: make test execution more robust
reneradoi Apr 30, 2024
2950429
test_storage.py: formatting
reneradoi Apr 30, 2024
d413e30
test_storage.py: use `destroy_unit` to scale down
reneradoi Apr 30, 2024
64089a9
test_storage.py: skip test case `test_storage_reuse_in_new_cluster_af…
reneradoi Apr 30, 2024
209620e
test_storage.py: get the continuous writes result after the scale-up,…
reneradoi May 2, 2024
eb4285a
test_storage.py: force unit removal when scaling down to ensure test …
reneradoi May 2, 2024
c708137
test_storage.py: create testfile before scaling down to check if data…
reneradoi May 2, 2024
fd953cc
test_storage.py: add `test_storage_reuse_after_scale_to_zero`
reneradoi May 2, 2024
ea7c596
test_storage.py: remove skip-mark
reneradoi May 2, 2024
8b70fbe
test_storage.py: linting result
reneradoi May 2, 2024
6b5d695
test_storage.py: skip the newly added test for scaling down to zero a…
reneradoi May 3, 2024
ee9e8c8
test_storage.py: linting result
reneradoi May 3, 2024
3de3a61
test_storage.py: continue writing data to check opensearch availability
reneradoi May 6, 2024
55b8ec4
test_storage.py: in test_storage_reuse_in_new_cluster_after_app_remov…
reneradoi May 6, 2024
83d92e3
test_storage.py: restart continuous writes after deployment of new cl…
reneradoi May 6, 2024
af6f769
update revision number of installed snap (fixes installation issue w…
reneradoi Apr 30, 2024
3e19d4d
test_storage.py: add storage pool, deploy model with persistent stora…
reneradoi Apr 30, 2024
98cdfec
test_storage.py: adjust testing workflow, deploy 2 units and scale do…
reneradoi Apr 30, 2024
577c6ca
test_storage.py: app status will not be active because after scaling …
reneradoi Apr 30, 2024
153601f
test_storage.py: force-destroy the application when removing the cluster
reneradoi Apr 30, 2024
c3c4f47
test_storage.py: fix comment
reneradoi Apr 30, 2024
4a54d74
test_storage.py: formatting
reneradoi Apr 30, 2024
f48f57a
test_storage.py: make test execution more robust
reneradoi Apr 30, 2024
38308c8
test_storage.py: formatting
reneradoi Apr 30, 2024
1279250
test_storage.py: use `destroy_unit` to scale down
reneradoi Apr 30, 2024
571be2f
test_storage.py: skip test case `test_storage_reuse_in_new_cluster_af…
reneradoi Apr 30, 2024
12be643
test_storage.py: get the continuous writes result after the scale-up,…
reneradoi May 2, 2024
ada890a
test_storage.py: force unit removal when scaling down to ensure test …
reneradoi May 2, 2024
ffe1a0b
test_storage.py: create testfile before scaling down to check if data…
reneradoi May 2, 2024
deec5ad
test_storage.py: add `test_storage_reuse_after_scale_to_zero`
reneradoi May 2, 2024
0a96226
test_storage.py: remove skip-mark
reneradoi May 2, 2024
69a4df8
test_storage.py: linting result
reneradoi May 2, 2024
c02215a
test_storage.py: skip the newly added test for scaling down to zero a…
reneradoi May 3, 2024
8803630
test_storage.py: linting result
reneradoi May 3, 2024
b19faf3
test_storage.py: continue writing data to check opensearch availability
reneradoi May 6, 2024
3b0f8e4
test_storage.py: in test_storage_reuse_in_new_cluster_after_app_remov…
reneradoi May 6, 2024
c21e090
test_storage.py: restart continuous writes after deployment of new cl…
reneradoi May 6, 2024
a9a3031
Merge remote-tracking branch 'origin/DPE-2119-attach-existing-storage…
reneradoi May 6, 2024
560cbaa
test_storage.py: sleep for some time when scaling down to avoid hook-…
reneradoi May 6, 2024
5811326
no longer delete `security_index_initialised` on storage_detaching
reneradoi May 23, 2024
b131eb8
adjustments to test execution workflow
reneradoi May 23, 2024
c499084
Merge branch 'main' into DPE-2119-attach-existing-storage
reneradoi May 23, 2024
2da6950
linting result
reneradoi May 23, 2024
4e5e642
Merge remote-tracking branch 'origin/DPE-2119-attach-existing-storage…
reneradoi May 23, 2024
5519a82
linting result
reneradoi May 23, 2024
9f24849
test_storage.py: scale up step by step
reneradoi May 24, 2024
2facf79
test_storage.py: add unit to self-signed-certificates app after machi…
reneradoi May 28, 2024
2ef965e
test_storage.py: add storage pool, deploy model with persistent stora…
reneradoi Apr 30, 2024
bb8cb25
test_storage.py: adjust testing workflow, deploy 2 units and scale do…
reneradoi Apr 30, 2024
58da533
test_storage.py: app status will not be active because after scaling …
reneradoi Apr 30, 2024
6154549
test_storage.py: force-destroy the application when removing the cluster
reneradoi Apr 30, 2024
1d0373c
test_storage.py: fix comment
reneradoi Apr 30, 2024
36d1078
test_storage.py: formatting
reneradoi Apr 30, 2024
22eb314
test_storage.py: make test execution more robust
reneradoi Apr 30, 2024
bd7195c
test_storage.py: formatting
reneradoi Apr 30, 2024
5417ac4
test_storage.py: use `destroy_unit` to scale down
reneradoi Apr 30, 2024
70e20d0
test_storage.py: skip test case `test_storage_reuse_in_new_cluster_af…
reneradoi Apr 30, 2024
e4dcada
test_storage.py: get the continuous writes result after the scale-up,…
reneradoi May 2, 2024
70dd7c4
test_storage.py: force unit removal when scaling down to ensure test …
reneradoi May 2, 2024
b8bf5a7
test_storage.py: create testfile before scaling down to check if data…
reneradoi May 2, 2024
317ad0b
test_storage.py: add `test_storage_reuse_after_scale_to_zero`
reneradoi May 2, 2024
517f6a6
test_storage.py: remove skip-mark
reneradoi May 2, 2024
e386913
test_storage.py: linting result
reneradoi May 2, 2024
4a9a334
test_storage.py: skip the newly added test for scaling down to zero a…
reneradoi May 3, 2024
36a932f
test_storage.py: linting result
reneradoi May 3, 2024
b442a80
test_storage.py: continue writing data to check opensearch availability
reneradoi May 6, 2024
7298a31
test_storage.py: in test_storage_reuse_in_new_cluster_after_app_remov…
reneradoi May 6, 2024
24e5f2f
test_storage.py: restart continuous writes after deployment of new cl…
reneradoi May 6, 2024
ba060ea
test_storage.py: force-destroy the application when removing the cluster
reneradoi Apr 30, 2024
781f989
test_storage.py: fix comment
reneradoi Apr 30, 2024
835e364
test_storage.py: formatting
reneradoi Apr 30, 2024
2a24adc
test_storage.py: make test execution more robust
reneradoi Apr 30, 2024
1b32f99
test_storage.py: formatting
reneradoi Apr 30, 2024
b9f15c9
test_storage.py: use `destroy_unit` to scale down
reneradoi Apr 30, 2024
887ffa4
test_storage.py: skip test case `test_storage_reuse_in_new_cluster_af…
reneradoi Apr 30, 2024
1a37ef2
test_storage.py: get the continuous writes result after the scale-up,…
reneradoi May 2, 2024
d3c5091
test_storage.py: force unit removal when scaling down to ensure test …
reneradoi May 2, 2024
fe69a9c
test_storage.py: create testfile before scaling down to check if data…
reneradoi May 2, 2024
2444354
test_storage.py: add `test_storage_reuse_after_scale_to_zero`
reneradoi May 2, 2024
4f33b5a
test_storage.py: remove skip-mark
reneradoi May 2, 2024
40176ef
test_storage.py: linting result
reneradoi May 2, 2024
26b8978
test_storage.py: skip the newly added test for scaling down to zero a…
reneradoi May 3, 2024
4daacbf
test_storage.py: linting result
reneradoi May 3, 2024
cb2fb41
test_storage.py: continue writing data to check opensearch availability
reneradoi May 6, 2024
4e57ccd
test_storage.py: in test_storage_reuse_in_new_cluster_after_app_remov…
reneradoi May 6, 2024
3005dfa
test_storage.py: restart continuous writes after deployment of new cl…
reneradoi May 6, 2024
c2b9b7b
test_storage.py: sleep for some time when scaling down to avoid hook-…
reneradoi May 6, 2024
19f843c
no longer delete `security_index_initialised` on storage_detaching
reneradoi May 23, 2024
a73d24b
adjustments to test execution workflow
reneradoi May 23, 2024
1fa2266
linting result
reneradoi May 23, 2024
b7caa6a
linting result
reneradoi May 23, 2024
5605b1d
test_storage.py: add unit to self-signed-certificates app after machi…
reneradoi May 28, 2024
c601ec5
Merge branch 'main' into DPE-2119-attach-existing-storage
reneradoi May 28, 2024
9ddcf8b
linting results
reneradoi May 28, 2024
eb93c9c
Merge remote-tracking branch 'origin/DPE-2119-attach-existing-storage…
reneradoi May 28, 2024
8fd9d01
linting results
reneradoi May 28, 2024
d78583b
remove currently unused test steps and imports
reneradoi May 28, 2024
2d5d821
format imports
reneradoi May 28, 2024
4e32356
Merge remote-tracking branch 'origin/DPE-2119-attach-existing-storage…
reneradoi May 28, 2024
dec9941
test_storage.py: for each unit to come up again after scaling down t…
reneradoi May 29, 2024
c8afcdf
test_storage.py: removing the application needs to be done carefully …
reneradoi May 29, 2024
157ae4f
bugfix, need to remove all units
reneradoi May 29, 2024
1fff8f3
scale down in reverse order
reneradoi May 29, 2024
4456b5e
temporarily skip some tests to speed up test run
reneradoi May 30, 2024
ebf780d
restart continuous writes to validate the new cluster is working corr…
reneradoi May 30, 2024
ddb5f96
deploy application with 2 units to avoid scaling up step later
reneradoi May 30, 2024
13afa4a
only check continuous writes increasing
reneradoi May 30, 2024
e0267a0
fix imports
reneradoi May 30, 2024
5f1f921
add restart of continuous writes to scale-to-zero-test also, remove t…
reneradoi May 30, 2024
e414aa4
adjust workflow for scale down
reneradoi May 30, 2024
a992298
clear continuous writes to avoid `index already exists` error
reneradoi May 30, 2024
9da6667
only checking, not restarting the continuous writes
reneradoi May 30, 2024
51aa8ff
linting result
reneradoi May 30, 2024
fb850c2
test_storage.py: more need to scale down carefully when removing the …
reneradoi May 31, 2024
e4ad40e
fix copyright date
reneradoi Jun 3, 2024
0420245
restart and assert continuous writes after scale down to zero
reneradoi Jun 3, 2024
b716b37
restart and assert continuous writes after cluster removal too
reneradoi Jun 3, 2024
12486d6
don't block the model when removing the application
reneradoi Jun 4, 2024
ebb7da0
test_storage.py: adjust workflow with app removal
reneradoi Jun 4, 2024
db41ade
add workaround for locking mechanism to avoid deadlocks when the .cha…
reneradoi Jun 6, 2024
c48f6bb
temporary fix to avoid timeout on the initialization of the security …
reneradoi Jun 6, 2024
4ab6b09
- wait until
reneradoi Jun 6, 2024
afde28f
another case where we need to fallback to peer databag lock
reneradoi Jun 6, 2024
6820215
assert the continuous writes differently
reneradoi Jun 6, 2024
f1d6142
remove temporary fix to avoid timeout on the initialization of the se…
reneradoi Jun 7, 2024
7988c16
Merge remote-tracking branch 'refs/remotes/origin/main' into DPE-2119…
reneradoi Jun 7, 2024
bb74991
revert to snap revision 50 (opensearch 2.13.0)
reneradoi Jun 7, 2024
cb15cc3
use snap revision 51 again (opensearch 2.14.0)
reneradoi Jun 10, 2024
269a4fa
in case of error checking which unit has the OpenSearch lock, only fa…
reneradoi Jun 10, 2024
9e75671
only fallback to peer databag lock if it's 1 units remaining
reneradoi Jun 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions lib/charms/opensearch/v0/opensearch_base_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,9 +530,6 @@ def _on_opensearch_data_storage_detaching(self, _: StorageDetachingEvent): # no
self.peers_data.delete(Scope.APP, "bootstrap_contributors_count")
self.peers_data.delete(Scope.APP, "nodes_config")

# todo: remove this if snap storage reuse is solved.
self.peers_data.delete(Scope.APP, "security_index_initialised")

# we attempt to flush the translog to disk
if self.opensearch.is_node_up():
try:
Expand Down
15 changes: 11 additions & 4 deletions lib/charms/opensearch/v0/opensearch_locking.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,8 @@ def _unit_with_lock(self, host) -> str | None:
retries=3,
)
except OpenSearchHttpError as e:
if e.response_code == 404:
# No unit has lock
if e.response_code in [404, 503]:
# No unit has lock or index not available
reneradoi marked this conversation as resolved.
Show resolved Hide resolved
return
raise
return document_data["unit-name"]
Expand Down Expand Up @@ -240,7 +240,13 @@ def acquired(self) -> bool: # noqa: C901
unit = self._unit_with_lock(host)
except OpenSearchHttpError:
logger.exception("Error checking which unit has OpenSearch lock")
return False
# if the node lock cannot be acquired, fall back to peer databag lock
# this avoids hitting deadlock situations in cases where
# the .charm_node_lock index is not available
if online_nodes <= 1:
return self._peer.acquired
else:
return False
# If online_nodes == 1, we should acquire the lock via the peer databag.
# If we acquired the lock via OpenSearch and this unit was stopping, we would be unable
# to release the OpenSearch lock. For example, when scaling to 0.
Expand Down Expand Up @@ -274,7 +280,8 @@ def acquired(self) -> bool: # noqa: C901
return False
else:
logger.exception("Error creating OpenSearch lock document")
return False
# in this case, try to acquire peer databag lock as fallback
return self._peer.acquired
else:
# Ensure write was successful on all nodes
# "It is important to note that this setting [`wait_for_active_shards`] greatly
Expand Down
161 changes: 126 additions & 35 deletions tests/integration/ha/test_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,21 @@

import asyncio
import logging
import subprocess
import time

import pytest
from pytest_operator.plugin import OpsTest

from ..ha.helpers import app_name, storage_id, storage_type
from ..ha.helpers import (
app_name,
assert_continuous_writes_increasing,
storage_id,
storage_type,
)
from ..ha.test_horizontal_scaling import IDLE_PERIOD
from ..helpers import APP_NAME, MODEL_CONFIG, SERIES, get_application_unit_ids
from ..helpers_deployments import wait_until
from ..tls.test_tls import TLS_CERTIFICATES_APP_NAME
from .continuous_writes import ContinuousWrites

Expand All @@ -29,11 +36,14 @@ async def test_build_and_deploy(ops_test: OpsTest) -> None:

my_charm = await ops_test.build_charm(".")
await ops_test.model.set_config(MODEL_CONFIG)
# this assumes the test is run on a lxd cloud
await ops_test.model.create_storage_pool("opensearch-pool", "lxd")
storage = {"opensearch-data": {"pool": "opensearch-pool", "size": 2048}}
# Deploy TLS Certificates operator.
config = {"ca-common-name": "CN_CA"}
await asyncio.gather(
ops_test.model.deploy(TLS_CERTIFICATES_APP_NAME, channel="stable", config=config),
ops_test.model.deploy(my_charm, num_units=1, series=SERIES),
ops_test.model.deploy(my_charm, num_units=1, series=SERIES, storage=storage),
reneradoi marked this conversation as resolved.
Show resolved Hide resolved
)

# Relate it to OpenSearch to set up TLS.
Expand All @@ -60,33 +70,34 @@ async def test_storage_reuse_after_scale_down(
"reuse of storage can only be used on deployments with persistent storage not on rootfs deployments"
)

# scale-down to 1 if multiple units
unit_ids = get_application_unit_ids(ops_test, app)
if len(unit_ids) > 1:
for unit_id in unit_ids[1:]:
await ops_test.model.applications[app].destroy_unit(f"{app}/{unit_id}")

await ops_test.model.wait_for_idle(
apps=[app],
status="active",
timeout=1000,
wait_for_exact_units=1,
idle_period=IDLE_PERIOD,
)
else:
# wait for enough data to be written
time.sleep(60)
# scale up to 2 units
await ops_test.model.applications[app].add_unit(count=1)
await ops_test.model.wait_for_idle(
apps=[app],
status="active",
timeout=1000,
wait_for_exact_units=2,
)

reneradoi marked this conversation as resolved.
Show resolved Hide resolved
writes_result = await c_writes.stop()

# get unit info
unit_id = get_application_unit_ids(ops_test, app)[0]
unit_id = get_application_unit_ids(ops_test, app)[1]
unit_storage_id = storage_id(ops_test, app, unit_id)

reneradoi marked this conversation as resolved.
Show resolved Hide resolved
# scale-down to 0
# create a testfile on the newly added unit to check if data in storage is persistent
testfile = "/var/snap/opensearch/common/testfile"
create_testfile_cmd = f"juju ssh {app}/{unit_id} -q sudo touch {testfile}"
subprocess.run(create_testfile_cmd, shell=True)

# scale-down to 1
await ops_test.model.applications[app].destroy_unit(f"{app}/{unit_id}")
await ops_test.model.wait_for_idle(
apps=[app], status="active", timeout=1000, wait_for_exact_units=0
# app status will not be active because after scaling down not all shards are assigned
apps=[app],
timeout=1000,
wait_for_exact_units=1,
idle_period=IDLE_PERIOD,
)

# add unit with storage attached
Expand All @@ -97,23 +108,86 @@ async def test_storage_reuse_after_scale_down(
assert return_code == 0, "Failed to add unit with storage"

await ops_test.model.wait_for_idle(
apps=[app], status="active", timeout=1000, wait_for_exact_units=1
apps=[app],
status="active",
timeout=1000,
wait_for_exact_units=2,
idle_period=IDLE_PERIOD,
)

# check the storage of the new unit
new_unit_id = get_application_unit_ids(ops_test, app)[0]
new_unit_id = get_application_unit_ids(ops_test, app)[1]
new_unit_storage_id = storage_id(ops_test, app, new_unit_id)
assert unit_storage_id == new_unit_storage_id, "Storage IDs mismatch."

# check if data is also imported
assert writes_result.count == (await c_writes.count())
assert writes_result.max_stored_id == (await c_writes.max_stored_id())

# check if the testfile is still there or was overwritten on installation
check_testfile_cmd = f"juju ssh {app}/{new_unit_id} -q sudo ls {testfile}"
assert testfile == subprocess.getoutput(check_testfile_cmd)


@pytest.mark.group(1)
@pytest.mark.abort_on_fail
async def test_storage_reuse_in_new_cluster_after_app_removal(
async def test_storage_reuse_after_scale_to_zero(
ops_test: OpsTest, c_writes: ContinuousWrites, c_writes_runner
):
"""Check storage is reused and data accessible after scaling down and up."""
app = (await app_name(ops_test)) or APP_NAME

if storage_type(ops_test, app) == "rootfs":
pytest.skip(
"reuse of storage can only be used on deployments with persistent storage not on rootfs deployments"
)

writes_result = await c_writes.stop()

# scale down to zero units in reverse order
unit_ids = get_application_unit_ids(ops_test, app)
storage_ids = {}
for unit_id in unit_ids[::-1]:
storage_ids[unit_id] = storage_id(ops_test, app, unit_id)
await ops_test.model.applications[app].destroy_unit(f"{app}/{unit_id}")
# give some time for removing each unit
time.sleep(60)

await ops_test.model.wait_for_idle(
# app status will not be active because after scaling down not all shards are assigned
apps=[app],
timeout=1000,
wait_for_exact_units=0,
)

# scale up again
for unit_id in unit_ids:
add_unit_cmd = f"add-unit {app} --model={ops_test.model.info.name} --attach-storage={storage_ids[unit_id]}"
return_code, _, _ = await ops_test.juju(*add_unit_cmd.split())
assert return_code == 0, f"Failed to add unit with storage {storage_ids[unit_id]}"
await ops_test.model.wait_for_idle(apps=[app], timeout=1000)

await ops_test.model.wait_for_idle(
apps=[app],
status="active",
timeout=1000,
wait_for_exact_units=len(unit_ids),
)

# check if data is also imported
assert writes_result.count == (await c_writes.count())
reneradoi marked this conversation as resolved.
Show resolved Hide resolved
assert writes_result.max_stored_id == (await c_writes.max_stored_id())
reneradoi marked this conversation as resolved.
Show resolved Hide resolved

# restart continuous writes and check if they can be written
await c_writes.start()
time.sleep(30)
await assert_continuous_writes_increasing(c_writes)


@pytest.mark.group(1)
@pytest.mark.abort_on_fail
async def test_storage_reuse_in_new_cluster_after_app_removal(
ops_test: OpsTest, c_writes: ContinuousWrites, c_balanced_writes_runner
):
"""Check storage is reused and data accessible after removing app and deploying new cluster."""
app = (await app_name(ops_test)) or APP_NAME
Expand All @@ -123,7 +197,7 @@ async def test_storage_reuse_in_new_cluster_after_app_removal(
"reuse of storage can only be used on deployments with persistent storage not on rootfs deployments"
)

# scale-down to 1 if multiple units
# scale-up to 3 to make it a cluster
reneradoi marked this conversation as resolved.
Show resolved Hide resolved
unit_ids = get_application_unit_ids(ops_test, app)
if len(unit_ids) < 3:
await ops_test.model.applications[app].add_unit(count=3 - len(unit_ids))
Expand All @@ -146,11 +220,8 @@ async def test_storage_reuse_in_new_cluster_after_app_removal(
for unit_id in get_application_unit_ids(ops_test, app):
storage_ids.append(storage_id(ops_test, app, unit_id))

# remove application
await ops_test.model.applications[app].destroy()

# wait a bit until all app deleted
time.sleep(60)
# remove the remaining application
await ops_test.model.remove_application(app, block_until_done=True)

# deploy new cluster
my_charm = await ops_test.build_charm(".")
Expand All @@ -159,6 +230,18 @@ async def test_storage_reuse_in_new_cluster_after_app_removal(
)
return_code, _, _ = await ops_test.juju(*deploy_cluster_with_storage_cmd.split())
assert return_code == 0, f"Failed to deploy app with storage {storage_ids[0]}"
await ops_test.model.integrate(app, TLS_CERTIFICATES_APP_NAME)

# wait for cluster to be deployed
await wait_until(
ops_test,
apps=[app],
apps_statuses=["active", "blocked"],
units_statuses=["active"],
wait_for_exact_units=1,
idle_period=IDLE_PERIOD,
timeout=2400,
)

# add unit with storage attached
for unit_storage_id in storage_ids[1:]:
Expand All @@ -168,12 +251,15 @@ async def test_storage_reuse_in_new_cluster_after_app_removal(
return_code, _, _ = await ops_test.juju(*add_unit_cmd.split())
assert return_code == 0, f"Failed to add unit with storage {unit_storage_id}"

await ops_test.model.integrate(app, TLS_CERTIFICATES_APP_NAME)
await ops_test.model.wait_for_idle(
apps=[TLS_CERTIFICATES_APP_NAME, APP_NAME],
status="active",
timeout=1000,
# wait for new cluster to settle down
await wait_until(
ops_test,
apps=[app],
apps_statuses=["active"],
units_statuses=["active"],
wait_for_exact_units=len(storage_ids),
idle_period=IDLE_PERIOD,
timeout=2400,
)
assert len(ops_test.model.applications[app].units) == len(storage_ids)

Expand All @@ -187,3 +273,8 @@ async def test_storage_reuse_in_new_cluster_after_app_removal(
# check if data is also imported
assert writes_result.count == (await c_writes.count())
assert writes_result.max_stored_id == (await c_writes.max_stored_id())

# restart continuous writes and check if they can be written
await c_writes.start()
time.sleep(60)
assert (await c_writes.count()) > 0, "Continuous writes not increasing"
Loading