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) 2024 Huawei Technologies Co., Ltd.
# SPDX-License-Identifier: BSD-3-Clause
#
import pytest
from api.cas import casadm
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 storage_devices.disk import DiskType, DiskTypeSet, DiskTypeLowerThan
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("core", DiskTypeLowerThan("cache"))
def test_core_inactive():
def test_core_inactive_stats_conf():
"""
1. Start cache with 3 cores.
2. Stop cache.
3. Remove one of core devices.
4. Load cache.
5. Check if cache has appropriate number of valid and inactive core devices.
title: Test for inactive core configuration statistics.
description: |
Test the cache inactive core configuration statistics after removing one of core devices
and loading cache.
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()
if stats.config_stats.inactive_core_devices != 0:
TestRun.fail("Inactive core in statistics after starting cache")
assert stats.config_stats.core_dev == 3
assert stats.config_stats.inactive_core_dev == 0
TestRun.LOGGER.info("Stopping cache")
with TestRun.step("Stop cache"):
cache.stop()
TestRun.LOGGER.info("Removing one of core devices")
core_device.remove_partitions()
core_device.create_partitions([Size(1, Unit.GibiByte), Size(1, Unit.GibiByte)])
with TestRun.step("Remove last core device"):
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 device"):
cache = casadm.start_cache(cache_device, load=True)
stats = cache.get_statistics()
assert stats.config_stats.core_dev == 3
assert stats.config_stats.inactive_core_dev == 1
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("core", DiskTypeLowerThan("cache"))
def test_core_inactive_stats():
def test_core_inactive_stats_usage():
"""
1. Start cache with 3 cores.
2. Switch cache into WB mode.
3. Issue IO to each core.
4. Stop cache without flush.
5. Remove two core devices.
6. Load cache.
7. Check if cache stats are equal to sum of valid and inactive cores stats.
8. Check if percentage values are calculated properly.
title: Test for inactive core usage statistics.
description: |
Test the cache inactive core usage statistics after removing one of core devices and loading
cache.
pass_criteria:
- Cache can be loaded with inactive core device.
- CAS correctly reports inactive core statistics in cache usage statistics after loading
cache.
"""
cache, core_device = prepare()
cache_device = cache.cache_device
core_number = 3
TestRun.LOGGER.info("Switching cache mode to WB")
cache.set_cache_mode(cache_mode=CacheMode.WB)
cores = cache.get_core_devices()
TestRun.LOGGER.info("Issue IO to each core")
for core in cores:
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, 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()
.input("/dev/zero")
.output(core.path)
.count(1000)
.block_size(Size(4, Unit.KibiByte))
).run()
)
dd.run()
TestRun.LOGGER.info("Stopping cache with dirty data")
cores[2].flush_core()
with TestRun.step("Flush last core"):
core_list[-1].flush_core()
with TestRun.step("Stop cache with dirty data"):
cache.stop(no_data_flush=True)
TestRun.LOGGER.info("Removing two of core devices")
core_device.remove_partitions()
core_device.create_partitions([Size(1, Unit.GibiByte)])
with TestRun.step("Removing two of core devices"):
core_device.remove_partition(part=core_device_partitions[0])
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)
# Accumulate valid cores stats
cores_occupancy = 0
cores_clean = 0
cores_dirty = 0
cores = cache.get_core_devices()
for core in cores:
with TestRun.step("Check cores statistics"):
active_cores_occupancy_stats = 0
active_cores_clean_stats = 0
active_cores_dirty_stats = 0
active_cores = cache.get_core_devices()
for core in active_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
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()
# Add inactive core 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
cache_usage_stats = cache_stats.usage_stats
assert cache_stats.usage_stats.occupancy.value == cores_occupancy
assert cache_stats.usage_stats.dirty.value == cores_dirty
assert cache_stats.usage_stats.clean.value == cores_clean
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
cache_stats_percentage = cache.get_statistics(percentage_val=True)
# Calculate expected percentage value of inactive core stats
inactive_occupancy_perc = (
cache_stats.inactive_usage_stats.inactive_occupancy.value
/ cache_stats.config_stats.cache_size.value
inactive_occupancy_perc = round(
100 * (cache_usage_stats.inactive_occupancy / cache_stats.config_stats.cache_size), 1
)
inactive_clean_perc = (
cache_stats.inactive_usage_stats.inactive_clean.value
/ cache_stats.usage_stats.occupancy.value
inactive_dirty_perc = round(
100 * (cache_usage_stats.inactive_dirty / cache_stats.usage_stats.occupancy), 1
)
inactive_dirty_perc = (
cache_stats.inactive_usage_stats.inactive_dirty.value
/ cache_stats.usage_stats.occupancy.value
inactive_clean_perc = round(
100 * (cache_usage_stats.inactive_clean / cache_stats.usage_stats.occupancy), 1
)
inactive_occupancy_perc = round(100 * inactive_occupancy_perc, 1)
inactive_clean_perc = round(100 * inactive_clean_perc, 1)
inactive_dirty_perc = round(100 * inactive_dirty_perc, 1)
TestRun.LOGGER.info(str(cache_stats_percentage))
assert (
inactive_occupancy_perc
== cache_stats_percentage.inactive_usage_stats.inactive_occupancy
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}"
)
assert (
inactive_clean_perc
== cache_stats_percentage.inactive_usage_stats.inactive_clean
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}"
)
assert (
inactive_dirty_perc
== cache_stats_percentage.inactive_usage_stats.inactive_dirty
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():
cache_device = TestRun.disks["cache"]
core_device = TestRun.disks["core"]
def get_inactive_cores(cache_id: int) -> list:
cores_dict = get_cas_devices_dict()["cores"].values()
cache_device.create_partitions([Size(500, Unit.MebiByte)])
core_device.create_partitions(
[Size(1, Unit.GibiByte), Size(1, Unit.GibiByte), Size(1, Unit.GibiByte)]
)
def is_active(core):
cache_device = cache_device.partitions[0]
core_device_1 = core_device.partitions[0]
core_device_2 = core_device.partitions[1]
core_device_3 = core_device.partitions[2]
return CoreStatus[core["status"].lower()] == CoreStatus.inactive
TestRun.LOGGER.info("Staring cache")
cache = casadm.start_cache(cache_device, force=True)
TestRun.LOGGER.info("Adding core device")
core_1 = cache.add_core(core_dev=core_device_1)
core_2 = cache.add_core(core_dev=core_device_2)
core_3 = cache.add_core(core_dev=core_device_3)
return cache, core_device
return [
Core(core["device_path"], core["cache_id"])
for core in cores_dict
if is_active(core) and core["cache_id"] == cache_id
]