tests: refactor test_inactive_cores

Signed-off-by: Kamil Gierszewski <kamil.gierszewski@huawei.com>
This commit is contained in:
Kamil Gierszewski 2024-09-27 16:48:40 +02:00
parent daea1a433a
commit 51962e4684
No known key found for this signature in database

View File

@ -1,13 +1,15 @@
# #
# Copyright(c) 2019-2021 Intel Corporation # Copyright(c) 2019-2021 Intel Corporation
# Copyright(c) 2024 Huawei Technologies Co., Ltd.
# SPDX-License-Identifier: BSD-3-Clause # SPDX-License-Identifier: BSD-3-Clause
# #
import pytest import pytest
from api.cas import casadm from api.cas import casadm
from api.cas.cache_config import CacheMode from api.cas.cache_config import CacheMode
from api.cas.casadm_parser import get_cas_devices_dict
from api.cas.core import Core, CoreStatus
from core.test_run import TestRun from core.test_run import TestRun
from storage_devices.disk import DiskType, DiskTypeSet, DiskTypeLowerThan from storage_devices.disk import DiskType, DiskTypeSet, DiskTypeLowerThan
from test_tools.dd import Dd from test_tools.dd import Dd
@ -16,152 +18,238 @@ from test_utils.size import Size, Unit
@pytest.mark.require_disk("cache", DiskTypeSet([DiskType.optane, DiskType.nand])) @pytest.mark.require_disk("cache", DiskTypeSet([DiskType.optane, DiskType.nand]))
@pytest.mark.require_disk("core", DiskTypeLowerThan("cache")) @pytest.mark.require_disk("core", DiskTypeLowerThan("cache"))
def test_core_inactive(): def test_core_inactive_stats_conf():
""" """
1. Start cache with 3 cores. title: Test for inactive core configuration statistics.
2. Stop cache. description: |
3. Remove one of core devices. Test the cache inactive core configuration statistics after removing one of core devices
4. Load cache. and loading cache.
5. Check if cache has appropriate number of valid and inactive core devices. pass_criteria:
- Cache can be loaded with inactive core device.
- CAS correctly reports inactive core statistics in cache configuration statistics after
loading cache.
""" """
cache, core_device = prepare() core_number = 3
cache_device = cache.cache_device with TestRun.step("Prepare cache and core devices"):
stats = cache.get_statistics() cache_device = TestRun.disks["cache"]
core_device = TestRun.disks["core"]
assert stats.config_stats.core_dev == 3 cache_device.create_partitions([Size(500, Unit.MebiByte)])
assert stats.config_stats.inactive_core_dev == 0 core_device.create_partitions([Size(1, Unit.GibiByte)] * core_number)
TestRun.LOGGER.info("Stopping cache") cache_device = cache_device.partitions[0]
cache.stop() core_device_partitions = core_device.partitions
TestRun.LOGGER.info("Removing one of core devices") with TestRun.step("Start cache"):
core_device.remove_partitions() cache = casadm.start_cache(cache_device, force=True)
core_device.create_partitions([Size(1, Unit.GibiByte), Size(1, Unit.GibiByte)])
TestRun.LOGGER.info("Loading cache with missing core device") with TestRun.step("Add cores to the cache"):
cache = casadm.start_cache(cache_device, load=True) for core_device_part in core_device_partitions:
stats = cache.get_statistics() cache.add_core(core_dev=core_device_part)
assert stats.config_stats.core_dev == 3 with TestRun.step("Check if correct number of inactive cores is displayed in cache statistics"):
assert stats.config_stats.inactive_core_dev == 1 stats = cache.get_statistics()
if stats.config_stats.inactive_core_devices != 0:
TestRun.fail("Inactive core in statistics after starting cache")
with TestRun.step("Stop cache"):
cache.stop()
with TestRun.step("Remove last core device"):
core_device.remove_partition(part=core_device_partitions[-1])
with TestRun.step("Load cache with missing core device"):
cache = casadm.start_cache(cache_device, load=True)
with TestRun.step(
"Check if correct number of cores and inactive cores is displayed in cache statistics"
):
stats = cache.get_statistics()
if stats.config_stats.core_dev != core_number:
TestRun.fail(
"Wrong number of cores after loading the cache\n"
f"Actual number of cores: {stats.config_stats.core_dev}\n"
f"Expected number of cores: {core_number}"
)
if stats.config_stats.inactive_core_devices != 1:
TestRun.fail(
"Wrong number of inactive cores after loading the cache\n"
f"Actual number of inactive cores: {stats.config_stats.inactive_core_devices}\n"
"Expected number of inactive cores: 1"
)
@pytest.mark.require_disk("cache", DiskTypeSet([DiskType.optane, DiskType.nand])) @pytest.mark.require_disk("cache", DiskTypeSet([DiskType.optane, DiskType.nand]))
@pytest.mark.require_disk("core", DiskTypeLowerThan("cache")) @pytest.mark.require_disk("core", DiskTypeLowerThan("cache"))
def test_core_inactive_stats(): def test_core_inactive_stats_usage():
""" """
1. Start cache with 3 cores. title: Test for inactive core usage statistics.
2. Switch cache into WB mode. description: |
3. Issue IO to each core. Test the cache inactive core usage statistics after removing one of core devices and loading
4. Stop cache without flush. cache.
5. Remove two core devices. pass_criteria:
6. Load cache. - Cache can be loaded with inactive core device.
7. Check if cache stats are equal to sum of valid and inactive cores stats. - CAS correctly reports inactive core statistics in cache usage statistics after loading
8. Check if percentage values are calculated properly. cache.
""" """
cache, core_device = prepare()
cache_device = cache.cache_device core_number = 3
TestRun.LOGGER.info("Switching cache mode to WB") with TestRun.step("Prepare cache and core devices"):
cache.set_cache_mode(cache_mode=CacheMode.WB) cache_device = TestRun.disks["cache"]
cores = cache.get_core_devices() core_device = TestRun.disks["core"]
TestRun.LOGGER.info("Issue IO to each core")
for core in cores:
dd = (
Dd()
.input("/dev/zero")
.output(core.path)
.count(1000)
.block_size(Size(4, Unit.KibiByte))
).run()
TestRun.LOGGER.info("Stopping cache with dirty data") cache_device.create_partitions([Size(500, Unit.MebiByte)])
cores[2].flush_core() core_device.create_partitions([Size(1, Unit.GibiByte)] * core_number)
cache.stop(no_data_flush=True)
TestRun.LOGGER.info("Removing two of core devices") cache_device = cache_device.partitions[0]
core_device.remove_partitions() core_device_partitions = core_device.partitions
core_device.create_partitions([Size(1, Unit.GibiByte)])
TestRun.LOGGER.info("Loading cache with missing core device") with TestRun.step("Start cache"):
cache = casadm.start_cache(cache_device, load=True) cache = casadm.start_cache(cache_device, force=True, cache_mode=CacheMode.WB)
# Accumulate valid cores stats with TestRun.step("Add cores to the cache"):
cores_occupancy = 0 core_list = [
cores_clean = 0 cache.add_core(core_dev=core_device_part) for core_device_part in core_device_partitions
cores_dirty = 0 ]
cores = cache.get_core_devices()
for core in cores:
core_stats = core.get_statistics()
cores_occupancy += core_stats.usage_stats.occupancy.value
cores_clean += core_stats.usage_stats.clean.value
cores_dirty += core_stats.usage_stats.dirty.value
cache_stats = cache.get_statistics() with TestRun.step("Run I/O to each core"):
# Add inactive core stats for core in core_list:
cores_occupancy += cache_stats.inactive_usage_stats.inactive_occupancy.value dd = (
cores_clean += cache_stats.inactive_usage_stats.inactive_clean.value Dd()
cores_dirty += cache_stats.inactive_usage_stats.inactive_dirty.value .input("/dev/zero")
.output(core.path)
.count(1000)
.block_size(Size(4, Unit.KibiByte))
)
dd.run()
assert cache_stats.usage_stats.occupancy.value == cores_occupancy with TestRun.step("Flush last core"):
assert cache_stats.usage_stats.dirty.value == cores_dirty core_list[-1].flush_core()
assert cache_stats.usage_stats.clean.value == cores_clean
cache_stats_percentage = cache.get_statistics(percentage_val=True) with TestRun.step("Stop cache with dirty data"):
# Calculate expected percentage value of inactive core stats cache.stop(no_data_flush=True)
inactive_occupancy_perc = (
cache_stats.inactive_usage_stats.inactive_occupancy.value
/ cache_stats.config_stats.cache_size.value
)
inactive_clean_perc = (
cache_stats.inactive_usage_stats.inactive_clean.value
/ cache_stats.usage_stats.occupancy.value
)
inactive_dirty_perc = (
cache_stats.inactive_usage_stats.inactive_dirty.value
/ cache_stats.usage_stats.occupancy.value
)
inactive_occupancy_perc = round(100 * inactive_occupancy_perc, 1) with TestRun.step("Removing two of core devices"):
inactive_clean_perc = round(100 * inactive_clean_perc, 1) core_device.remove_partition(part=core_device_partitions[0])
inactive_dirty_perc = round(100 * inactive_dirty_perc, 1) core_device.remove_partition(part=core_device_partitions[1])
TestRun.LOGGER.info(str(cache_stats_percentage)) with TestRun.step("Load cache with missing core devices"):
assert ( cache = casadm.start_cache(cache_device, load=True)
inactive_occupancy_perc
== cache_stats_percentage.inactive_usage_stats.inactive_occupancy with TestRun.step("Check cores statistics"):
) active_cores_occupancy_stats = 0
assert ( active_cores_clean_stats = 0
inactive_clean_perc active_cores_dirty_stats = 0
== cache_stats_percentage.inactive_usage_stats.inactive_clean
) active_cores = cache.get_core_devices()
assert ( for core in active_cores:
inactive_dirty_perc core_stats = core.get_statistics()
== cache_stats_percentage.inactive_usage_stats.inactive_dirty active_cores_occupancy_stats += core_stats.usage_stats.occupancy
) active_cores_clean_stats += core_stats.usage_stats.clean
active_cores_dirty_stats += core_stats.usage_stats.dirty
inactive_cores_occupancy_stats = 0
inactive_cores_clean_stats = 0
inactive_cores_dirty_stats = 0
inactive_cores = get_inactive_cores(cache_id=cache.cache_id)
for core in inactive_cores:
core_stats = core.get_statistics()
inactive_cores_occupancy_stats += core_stats.usage_stats.occupancy
inactive_cores_clean_stats += core_stats.usage_stats.clean
inactive_cores_dirty_stats += core_stats.usage_stats.dirty
cache_stats = cache.get_statistics()
cache_usage_stats = cache_stats.usage_stats
total_cores_occupancy_stats = active_cores_occupancy_stats + inactive_cores_occupancy_stats
total_cores_dirty_stats = active_cores_dirty_stats + inactive_cores_dirty_stats
total_cores_clean_stats = active_cores_clean_stats + inactive_cores_clean_stats
if cache_usage_stats.occupancy != total_cores_occupancy_stats:
TestRun.LOGGER.error(
"Wrong number of occupancy blocks in cache usage stats\n"
f"Actual number of occupancy blocks: {cache_usage_stats.occupancy}\n"
f"Expected number of occupancy blocks: {total_cores_occupancy_stats}"
)
if cache_usage_stats.dirty != total_cores_dirty_stats:
TestRun.LOGGER.error(
"Wrong number of dirty blocks in cache usage stats\n"
f"Actual number of dirty blocks: {cache_usage_stats.dirty}\n"
f"Expected number of dirty blocks: {total_cores_dirty_stats}"
)
if cache_usage_stats.clean != total_cores_clean_stats:
TestRun.LOGGER.error(
"Wrong number of clean blocks in cache usage stats\n"
f"Actual number of clean blocks: {cache_usage_stats.clean}\n"
f"Expected number of clean blocks: {total_cores_clean_stats}"
)
if cache_usage_stats.inactive_occupancy != inactive_cores_occupancy_stats:
TestRun.LOGGER.error(
"Wrong number of occupancy blocks in inactive cache usage stats\n"
f"Actual number of occupancy blocks: {cache_usage_stats.inactive_occupancy}\n"
f"Expected number of occupancy blocks: {inactive_cores_occupancy_stats}"
)
if cache_usage_stats.inactive_dirty != inactive_cores_dirty_stats:
TestRun.LOGGER.error(
"Wrong number of dirty blocks in cache inactive usage stats\n"
f"Actual number of dirty blocks: {cache_usage_stats.inactive_dirty}\n"
f"Expected number of dirty blocks: {inactive_cores_dirty_stats}"
)
if cache_usage_stats.inactive_clean != inactive_cores_clean_stats:
TestRun.LOGGER.error(
"Wrong number of clean blocks in cache inactive usage stats\n"
f"Actual number of clean blocks: {cache_usage_stats.inactive_clean}\n"
f"Expected number of clean blocks: {inactive_cores_clean_stats}"
)
cache_usage_stats_percentage = cache.get_statistics(percentage_val=True).usage_stats
# Calculate expected percentage value of inactive core stats
inactive_occupancy_perc = round(
100 * (cache_usage_stats.inactive_occupancy / cache_stats.config_stats.cache_size), 1
)
inactive_dirty_perc = round(
100 * (cache_usage_stats.inactive_dirty / cache_stats.usage_stats.occupancy), 1
)
inactive_clean_perc = round(
100 * (cache_usage_stats.inactive_clean / cache_stats.usage_stats.occupancy), 1
)
if cache_usage_stats_percentage.inactive_occupancy != inactive_occupancy_perc:
TestRun.LOGGER.error(
"Wrong occupancy blocks percentage in usage stats\n"
f"Actual number of occupancy blocks percentage:"
f" {cache_usage_stats_percentage.inactive_occupancy}\n"
f"Expected number of occupancy blocks percentage: {inactive_occupancy_perc}"
)
if cache_usage_stats_percentage.inactive_dirty != inactive_dirty_perc:
TestRun.LOGGER.error(
"Wrong dirty blocks percentage in usage stats\n "
"Actual number of dirty blocks percentage: "
f"{cache_usage_stats_percentage.inactive_dirty}\n"
f"Expected number of dirty blocks percentage: {inactive_dirty_perc}"
)
if cache_usage_stats_percentage.inactive_clean != inactive_clean_perc:
TestRun.LOGGER.error(
"Wrong clean blocks percentage in usage stats\n"
"Actual number of clean blocks percentage: "
f"{cache_usage_stats.inactive_clean}\n"
f"Expected number of clean blocks percentage: {inactive_cores_clean_stats}"
)
def prepare(): def get_inactive_cores(cache_id: int) -> list:
cache_device = TestRun.disks["cache"] cores_dict = get_cas_devices_dict()["cores"].values()
core_device = TestRun.disks["core"]
cache_device.create_partitions([Size(500, Unit.MebiByte)]) def is_active(core):
core_device.create_partitions(
[Size(1, Unit.GibiByte), Size(1, Unit.GibiByte), Size(1, Unit.GibiByte)]
)
cache_device = cache_device.partitions[0] return CoreStatus[core["status"].lower()] == CoreStatus.inactive
core_device_1 = core_device.partitions[0]
core_device_2 = core_device.partitions[1]
core_device_3 = core_device.partitions[2]
TestRun.LOGGER.info("Staring cache") return [
cache = casadm.start_cache(cache_device, force=True) Core(core["device_path"], core["cache_id"])
TestRun.LOGGER.info("Adding core device") for core in cores_dict
core_1 = cache.add_core(core_dev=core_device_1) if is_active(core) and core["cache_id"] == cache_id
core_2 = cache.add_core(core_dev=core_device_2) ]
core_3 = cache.add_core(core_dev=core_device_3)
return cache, core_device