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"):
cache_device = TestRun.disks["cache"]
core_device = TestRun.disks["core"]
cache_device.create_partitions([Size(500, Unit.MebiByte)])
core_device.create_partitions([Size(1, Unit.GibiByte)] * core_number)
cache_device = cache_device.partitions[0]
core_device_partitions = core_device.partitions
with TestRun.step("Start cache"):
cache = casadm.start_cache(cache_device, force=True)
with TestRun.step("Add cores to the cache"):
for core_device_part in core_device_partitions:
cache.add_core(core_dev=core_device_part)
with TestRun.step("Check if correct number of inactive cores is displayed in cache statistics"):
stats = cache.get_statistics() stats = cache.get_statistics()
if stats.config_stats.inactive_core_devices != 0:
TestRun.fail("Inactive core in statistics after starting cache")
assert stats.config_stats.core_dev == 3 with TestRun.step("Stop cache"):
assert stats.config_stats.inactive_core_dev == 0
TestRun.LOGGER.info("Stopping cache")
cache.stop() cache.stop()
TestRun.LOGGER.info("Removing one of core devices") with TestRun.step("Remove last core device"):
core_device.remove_partitions() core_device.remove_partition(part=core_device_partitions[-1])
core_device.create_partitions([Size(1, Unit.GibiByte), Size(1, Unit.GibiByte)])
TestRun.LOGGER.info("Loading cache with missing core device") with TestRun.step("Load cache with missing core device"):
cache = casadm.start_cache(cache_device, load=True) cache = casadm.start_cache(cache_device, load=True)
stats = cache.get_statistics()
assert stats.config_stats.core_dev == 3 with TestRun.step(
assert stats.config_stats.inactive_core_dev == 1 "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: cache_device.create_partitions([Size(500, Unit.MebiByte)])
core_device.create_partitions([Size(1, Unit.GibiByte)] * core_number)
cache_device = cache_device.partitions[0]
core_device_partitions = core_device.partitions
with TestRun.step("Start cache"):
cache = casadm.start_cache(cache_device, force=True, cache_mode=CacheMode.WB)
with TestRun.step("Add cores to the cache"):
core_list = [
cache.add_core(core_dev=core_device_part) for core_device_part in core_device_partitions
]
with TestRun.step("Run I/O to each core"):
for core in core_list:
dd = ( dd = (
Dd() Dd()
.input("/dev/zero") .input("/dev/zero")
.output(core.path) .output(core.path)
.count(1000) .count(1000)
.block_size(Size(4, Unit.KibiByte)) .block_size(Size(4, Unit.KibiByte))
).run() )
dd.run()
TestRun.LOGGER.info("Stopping cache with dirty data") with TestRun.step("Flush last core"):
cores[2].flush_core() core_list[-1].flush_core()
with TestRun.step("Stop cache with dirty data"):
cache.stop(no_data_flush=True) cache.stop(no_data_flush=True)
TestRun.LOGGER.info("Removing two of core devices") with TestRun.step("Removing two of core devices"):
core_device.remove_partitions() core_device.remove_partition(part=core_device_partitions[0])
core_device.create_partitions([Size(1, Unit.GibiByte)]) core_device.remove_partition(part=core_device_partitions[1])
TestRun.LOGGER.info("Loading cache with missing core device") with TestRun.step("Load cache with missing core devices"):
cache = casadm.start_cache(cache_device, load=True) cache = casadm.start_cache(cache_device, load=True)
# Accumulate valid cores stats with TestRun.step("Check cores statistics"):
cores_occupancy = 0 active_cores_occupancy_stats = 0
cores_clean = 0 active_cores_clean_stats = 0
cores_dirty = 0 active_cores_dirty_stats = 0
cores = cache.get_core_devices()
for core in cores: active_cores = cache.get_core_devices()
for core in active_cores:
core_stats = core.get_statistics() core_stats = core.get_statistics()
cores_occupancy += core_stats.usage_stats.occupancy.value active_cores_occupancy_stats += core_stats.usage_stats.occupancy
cores_clean += core_stats.usage_stats.clean.value active_cores_clean_stats += core_stats.usage_stats.clean
cores_dirty += core_stats.usage_stats.dirty.value 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_stats = cache.get_statistics()
# Add inactive core stats cache_usage_stats = cache_stats.usage_stats
cores_occupancy += cache_stats.inactive_usage_stats.inactive_occupancy.value
cores_clean += cache_stats.inactive_usage_stats.inactive_clean.value
cores_dirty += cache_stats.inactive_usage_stats.inactive_dirty.value
assert cache_stats.usage_stats.occupancy.value == cores_occupancy total_cores_occupancy_stats = active_cores_occupancy_stats + inactive_cores_occupancy_stats
assert cache_stats.usage_stats.dirty.value == cores_dirty total_cores_dirty_stats = active_cores_dirty_stats + inactive_cores_dirty_stats
assert cache_stats.usage_stats.clean.value == cores_clean 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
cache_stats_percentage = cache.get_statistics(percentage_val=True)
# Calculate expected percentage value of inactive core stats # Calculate expected percentage value of inactive core stats
inactive_occupancy_perc = ( inactive_occupancy_perc = round(
cache_stats.inactive_usage_stats.inactive_occupancy.value 100 * (cache_usage_stats.inactive_occupancy / cache_stats.config_stats.cache_size), 1
/ cache_stats.config_stats.cache_size.value
) )
inactive_clean_perc = ( inactive_dirty_perc = round(
cache_stats.inactive_usage_stats.inactive_clean.value 100 * (cache_usage_stats.inactive_dirty / cache_stats.usage_stats.occupancy), 1
/ cache_stats.usage_stats.occupancy.value
) )
inactive_dirty_perc = ( inactive_clean_perc = round(
cache_stats.inactive_usage_stats.inactive_dirty.value 100 * (cache_usage_stats.inactive_clean / cache_stats.usage_stats.occupancy), 1
/ cache_stats.usage_stats.occupancy.value
) )
inactive_occupancy_perc = round(100 * inactive_occupancy_perc, 1) if cache_usage_stats_percentage.inactive_occupancy != inactive_occupancy_perc:
inactive_clean_perc = round(100 * inactive_clean_perc, 1) TestRun.LOGGER.error(
inactive_dirty_perc = round(100 * inactive_dirty_perc, 1) "Wrong occupancy blocks percentage in usage stats\n"
f"Actual number of occupancy blocks percentage:"
TestRun.LOGGER.info(str(cache_stats_percentage)) f" {cache_usage_stats_percentage.inactive_occupancy}\n"
assert ( f"Expected number of occupancy blocks percentage: {inactive_occupancy_perc}"
inactive_occupancy_perc
== cache_stats_percentage.inactive_usage_stats.inactive_occupancy
) )
assert ( if cache_usage_stats_percentage.inactive_dirty != inactive_dirty_perc:
inactive_clean_perc TestRun.LOGGER.error(
== cache_stats_percentage.inactive_usage_stats.inactive_clean "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}"
) )
assert ( if cache_usage_stats_percentage.inactive_clean != inactive_clean_perc:
inactive_dirty_perc TestRun.LOGGER.error(
== cache_stats_percentage.inactive_usage_stats.inactive_dirty "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