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
stats = cache.get_statistics()
with TestRun.step("Prepare cache and core devices"):
cache_device = TestRun.disks["cache"]
core_device = TestRun.disks["core"]
assert stats.config_stats.core_dev == 3
assert stats.config_stats.inactive_core_dev == 0
cache_device.create_partitions([Size(500, Unit.MebiByte)])
core_device.create_partitions([Size(1, Unit.GibiByte)] * core_number)
TestRun.LOGGER.info("Stopping cache")
cache.stop()
cache_device = cache_device.partitions[0]
core_device_partitions = core_device.partitions
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("Start cache"):
cache = casadm.start_cache(cache_device, force=True)
TestRun.LOGGER.info("Loading cache with missing core device")
cache = casadm.start_cache(cache_device, load=True)
stats = cache.get_statistics()
with TestRun.step("Add cores to the cache"):
for core_device_part in core_device_partitions:
cache.add_core(core_dev=core_device_part)
assert stats.config_stats.core_dev == 3
assert stats.config_stats.inactive_core_dev == 1
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")
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("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:
dd = (
Dd()
.input("/dev/zero")
.output(core.path)
.count(1000)
.block_size(Size(4, Unit.KibiByte))
).run()
with TestRun.step("Prepare cache and core devices"):
cache_device = TestRun.disks["cache"]
core_device = TestRun.disks["core"]
TestRun.LOGGER.info("Stopping cache with dirty data")
cores[2].flush_core()
cache.stop(no_data_flush=True)
cache_device.create_partitions([Size(500, Unit.MebiByte)])
core_device.create_partitions([Size(1, Unit.GibiByte)] * core_number)
TestRun.LOGGER.info("Removing two of core devices")
core_device.remove_partitions()
core_device.create_partitions([Size(1, Unit.GibiByte)])
cache_device = cache_device.partitions[0]
core_device_partitions = core_device.partitions
TestRun.LOGGER.info("Loading cache with missing core device")
cache = casadm.start_cache(cache_device, load=True)
with TestRun.step("Start cache"):
cache = casadm.start_cache(cache_device, force=True, cache_mode=CacheMode.WB)
# Accumulate valid cores stats
cores_occupancy = 0
cores_clean = 0
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
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
]
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
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))
)
dd.run()
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
with TestRun.step("Flush last core"):
core_list[-1].flush_core()
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_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
)
with TestRun.step("Stop cache with dirty data"):
cache.stop(no_data_flush=True)
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)
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(str(cache_stats_percentage))
assert (
inactive_occupancy_perc
== cache_stats_percentage.inactive_usage_stats.inactive_occupancy
)
assert (
inactive_clean_perc
== cache_stats_percentage.inactive_usage_stats.inactive_clean
)
assert (
inactive_dirty_perc
== cache_stats_percentage.inactive_usage_stats.inactive_dirty
)
with TestRun.step("Load cache with missing core devices"):
cache = casadm.start_cache(cache_device, load=True)
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()
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():
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
]