Merge pull request #936 from Deixx/api-remove-inactive
Remove inactive commands tests and API update
This commit is contained in:
commit
4c7661623a
@ -121,9 +121,12 @@ class Cache:
|
|||||||
def add_core(self, core_dev, core_id: int = None):
|
def add_core(self, core_dev, core_id: int = None):
|
||||||
return casadm.add_core(self, core_dev, core_id)
|
return casadm.add_core(self, core_dev, core_id)
|
||||||
|
|
||||||
def remove_core(self, core_id, force: bool = False):
|
def remove_core(self, core_id: int, force: bool = False):
|
||||||
return casadm.remove_core(self.cache_id, core_id, force)
|
return casadm.remove_core(self.cache_id, core_id, force)
|
||||||
|
|
||||||
|
def remove_inactive_core(self, core_id: int, force: bool = False):
|
||||||
|
return casadm.remove_inactive(self.cache_id, core_id, force)
|
||||||
|
|
||||||
def reset_counters(self):
|
def reset_counters(self):
|
||||||
return casadm.reset_counters(self.cache_id)
|
return casadm.reset_counters(self.cache_id)
|
||||||
|
|
||||||
|
@ -69,6 +69,14 @@ def remove_core(cache_id: int, core_id: int, force: bool = False, shortcut: bool
|
|||||||
raise CmdException("Failed to remove core.", output)
|
raise CmdException("Failed to remove core.", output)
|
||||||
|
|
||||||
|
|
||||||
|
def remove_inactive(cache_id: int, core_id: int, force: bool = False, shortcut: bool = False):
|
||||||
|
output = TestRun.executor.run(
|
||||||
|
remove_inactive_cmd(
|
||||||
|
cache_id=str(cache_id), core_id=str(core_id), force=force, shortcut=shortcut))
|
||||||
|
if output.exit_code != 0:
|
||||||
|
raise CmdException("Failed to remove inactive core.", output)
|
||||||
|
|
||||||
|
|
||||||
def remove_detached(core_device: Device, shortcut: bool = False):
|
def remove_detached(core_device: Device, shortcut: bool = False):
|
||||||
output = TestRun.executor.run(
|
output = TestRun.executor.run(
|
||||||
remove_detached_cmd(core_device=core_device.path, shortcut=shortcut))
|
remove_detached_cmd(core_device=core_device.path, shortcut=shortcut))
|
||||||
|
@ -55,6 +55,14 @@ def remove_core_cmd(cache_id: str, core_id: str, force: bool = False, shortcut:
|
|||||||
return casadm_bin + command
|
return casadm_bin + command
|
||||||
|
|
||||||
|
|
||||||
|
def remove_inactive_cmd(cache_id: str, core_id: str, force: bool = False, shortcut: bool = False):
|
||||||
|
command = f" --remove-inactive {'-i' if shortcut else '--cache-id'} {cache_id} " \
|
||||||
|
f"{'-j' if shortcut else '--core-id'} {core_id}"
|
||||||
|
if force:
|
||||||
|
command += " -f" if shortcut else " --force"
|
||||||
|
return casadm_bin + command
|
||||||
|
|
||||||
|
|
||||||
def remove_detached_cmd(core_device: str, shortcut: bool = False):
|
def remove_detached_cmd(core_device: str, shortcut: bool = False):
|
||||||
command = " --remove-detached" + (" -d " if shortcut else " --device ") + core_device
|
command = " --remove-detached" + (" -d " if shortcut else " --device ") + core_device
|
||||||
return casadm_bin + command
|
return casadm_bin + command
|
||||||
|
@ -30,9 +30,13 @@ reinitialize_with_force_or_recovery = [
|
|||||||
r" discard on-disk metadata and start fresh cache instance\."
|
r" discard on-disk metadata and start fresh cache instance\."
|
||||||
]
|
]
|
||||||
|
|
||||||
remove_inactive_core = [
|
remove_inactive_core_with_remove_command = [
|
||||||
r"Error while removing core device \d+ from cache instance \d+",
|
r"Core is inactive\. To manage the inactive core use '--remove-inactive' command\."
|
||||||
r"Core device is in inactive state"
|
]
|
||||||
|
|
||||||
|
remove_inactive_dirty_core = [
|
||||||
|
r"The cache contains dirty data assigned to the core\. If you want to ",
|
||||||
|
r"continue, please use --force option\.\nWarning: the data will be lost"
|
||||||
]
|
]
|
||||||
|
|
||||||
stop_cache_incomplete = [
|
stop_cache_incomplete = [
|
||||||
|
@ -2,14 +2,21 @@
|
|||||||
# Copyright(c) 2019-2021 Intel Corporation
|
# Copyright(c) 2019-2021 Intel Corporation
|
||||||
# SPDX-License-Identifier: BSD-3-Clause-Clear
|
# SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||||
#
|
#
|
||||||
|
from datetime import timedelta
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from aenum import Enum
|
||||||
|
|
||||||
from api.cas.casadm_parser import *
|
from api.cas import casadm
|
||||||
from api.cas.cli import *
|
from api.cas.cache_config import SeqCutOffParameters, SeqCutOffPolicy
|
||||||
|
from api.cas.casadm_params import OutputFormat, StatsFilter
|
||||||
|
from api.cas.casadm_parser import get_statistics, get_seq_cut_off_parameters
|
||||||
from api.cas.statistics import CoreStats, CoreIoClassStats
|
from api.cas.statistics import CoreStats, CoreIoClassStats
|
||||||
|
from core.test_run_utils import TestRun
|
||||||
|
from storage_devices.device import Device
|
||||||
from test_tools import fs_utils, disk_utils
|
from test_tools import fs_utils, disk_utils
|
||||||
from test_utils.os_utils import *
|
from test_utils.os_utils import wait, sync
|
||||||
from test_utils.os_utils import wait
|
from test_utils.size import Unit, Size
|
||||||
|
|
||||||
|
|
||||||
class CoreStatus(Enum):
|
class CoreStatus(Enum):
|
||||||
@ -28,6 +35,7 @@ class Core(Device):
|
|||||||
self.core_device = Device(core_device)
|
self.core_device = Device(core_device)
|
||||||
self.path = None
|
self.path = None
|
||||||
core_info = self.__get_core_info()
|
core_info = self.__get_core_info()
|
||||||
|
# "-" is special case for cores in core pool
|
||||||
if core_info["core_id"] != "-":
|
if core_info["core_id"] != "-":
|
||||||
self.core_id = int(core_info["core_id"])
|
self.core_id = int(core_info["core_id"])
|
||||||
if core_info["exp_obj"] != "-":
|
if core_info["exp_obj"] != "-":
|
||||||
@ -37,16 +45,11 @@ class Core(Device):
|
|||||||
self.block_size = None
|
self.block_size = None
|
||||||
|
|
||||||
def __get_core_info(self):
|
def __get_core_info(self):
|
||||||
output = TestRun.executor.run(
|
output = casadm.list_caches(OutputFormat.csv, by_id_path=True)
|
||||||
list_cmd(OutputFormat.csv.name, by_id_path=False))
|
split_line = next(
|
||||||
if output.exit_code != 0:
|
line.split(',') for line in output.stdout.splitlines()
|
||||||
raise Exception("Failed to execute list caches command.")
|
if line.startswith("core") and self.core_device.path in line
|
||||||
output_lines = output.stdout.splitlines()
|
)
|
||||||
for line in output_lines:
|
|
||||||
split_line = line.split(',')
|
|
||||||
if split_line[0] == "core" and (
|
|
||||||
split_line[2] == os.path.join("/dev", self.core_device.get_device_id())
|
|
||||||
or split_line[5] == self.path):
|
|
||||||
return {"core_id": split_line[1],
|
return {"core_id": split_line[1],
|
||||||
"core_device": split_line[2],
|
"core_device": split_line[2],
|
||||||
"status": split_line[3],
|
"status": split_line[3],
|
||||||
@ -104,6 +107,9 @@ class Core(Device):
|
|||||||
def remove_core(self, force: bool = False):
|
def remove_core(self, force: bool = False):
|
||||||
return casadm.remove_core(self.cache_id, self.core_id, force)
|
return casadm.remove_core(self.cache_id, self.core_id, force)
|
||||||
|
|
||||||
|
def remove_inactive(self, force: bool = False):
|
||||||
|
return casadm.remove_inactive(self.cache_id, self.core_id, force)
|
||||||
|
|
||||||
def reset_counters(self):
|
def reset_counters(self):
|
||||||
return casadm.reset_counters(self.cache_id, self.core_id)
|
return casadm.reset_counters(self.cache_id, self.core_id)
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ def pytest_runtest_teardown():
|
|||||||
InitConfig.create_default_init_config()
|
InitConfig.create_default_init_config()
|
||||||
DeviceMapper.remove_all()
|
DeviceMapper.remove_all()
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
TestRun.LOGGER.warning(f"Exception occured during platform cleanup.\n"
|
TestRun.LOGGER.warning(f"Exception occurred during platform cleanup.\n"
|
||||||
f"{str(ex)}\n{traceback.format_exc()}")
|
f"{str(ex)}\n{traceback.format_exc()}")
|
||||||
|
|
||||||
TestRun.LOGGER.end()
|
TestRun.LOGGER.end()
|
||||||
|
@ -5,11 +5,13 @@
|
|||||||
|
|
||||||
import time
|
import time
|
||||||
from random import shuffle
|
from random import shuffle
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from api.cas import casadm, cli, cli_messages
|
from api.cas import casadm, cli, cli_messages
|
||||||
from api.cas.cache_config import CacheStatus, SeqCutOffPolicy, CacheModeTrait
|
from api.cas.cache_config import CacheStatus, SeqCutOffPolicy, CacheModeTrait, CacheMode, \
|
||||||
from api.cas.core import CoreStatus, CacheMode, CleaningPolicy, FlushParametersAlru, File
|
CleaningPolicy, FlushParametersAlru
|
||||||
|
from api.cas.core import CoreStatus
|
||||||
from api.cas.init_config import InitConfig
|
from api.cas.init_config import InitConfig
|
||||||
from api.cas.statistics import CacheStats
|
from api.cas.statistics import CacheStats
|
||||||
from core.test_run import TestRun
|
from core.test_run import TestRun
|
||||||
@ -18,8 +20,8 @@ from test_tools.dd import Dd
|
|||||||
from test_tools.disk_utils import Filesystem
|
from test_tools.disk_utils import Filesystem
|
||||||
from test_tools.fio.fio import Fio
|
from test_tools.fio.fio import Fio
|
||||||
from test_tools.fio.fio_param import IoEngine, ReadWrite
|
from test_tools.fio.fio_param import IoEngine, ReadWrite
|
||||||
from test_utils import os_utils
|
from test_utils.filesystem.file import File
|
||||||
from test_utils.os_utils import Udev
|
from test_utils.os_utils import Udev, sync
|
||||||
from test_utils.output import CmdException
|
from test_utils.output import CmdException
|
||||||
from test_utils.size import Size, Unit
|
from test_utils.size import Size, Unit
|
||||||
from test_utils.time import Time
|
from test_utils.time import Time
|
||||||
@ -326,7 +328,7 @@ def test_preserve_data_for_inactive_device():
|
|||||||
.count(100) \
|
.count(100) \
|
||||||
.block_size(Size(1, Unit.Blocks512))
|
.block_size(Size(1, Unit.Blocks512))
|
||||||
dd.run()
|
dd.run()
|
||||||
os_utils.sync()
|
sync()
|
||||||
md5_after_create = test_file.md5sum()
|
md5_after_create = test_file.md5sum()
|
||||||
cache_stats_before_stop = cache.get_statistics()
|
cache_stats_before_stop = cache.get_statistics()
|
||||||
core_stats_before_stop = core.get_statistics()
|
core_stats_before_stop = core.get_statistics()
|
||||||
@ -498,7 +500,7 @@ def test_print_statistics_inactive(cache_mode):
|
|||||||
f"({inactive_stats_after.inactive_usage_stats.inactive_occupancy}).")
|
f"({inactive_stats_after.inactive_usage_stats.inactive_occupancy}).")
|
||||||
|
|
||||||
with TestRun.step("Remove inactive core from cache and check if cache is in running state."):
|
with TestRun.step("Remove inactive core from cache and check if cache is in running state."):
|
||||||
cache.remove_core(second_core.core_id, force=True)
|
cache.remove_inactive_core(second_core.core_id)
|
||||||
cache_status = cache.get_status()
|
cache_status = cache.get_status()
|
||||||
if cache_status != CacheStatus.running:
|
if cache_status != CacheStatus.running:
|
||||||
TestRun.fail(f"Cache did not change status to 'running' after plugging core device. "
|
TestRun.fail(f"Cache did not change status to 'running' after plugging core device. "
|
||||||
@ -640,27 +642,49 @@ def test_remove_inactive_devices():
|
|||||||
TestRun.fail(f"Each core should be in inactive state. "
|
TestRun.fail(f"Each core should be in inactive state. "
|
||||||
f"Actual states:\n{casadm.list_caches().stdout}")
|
f"Actual states:\n{casadm.list_caches().stdout}")
|
||||||
|
|
||||||
with TestRun.step("Try removing CAS device without ‘force’ option. Verify that for "
|
with TestRun.step("Try removing CAS devices using remove command. "
|
||||||
"dirty CAS devices operation is blocked, proper message is displayed "
|
"Operation should be blocked and proper message displayed."):
|
||||||
"and device is still listed."):
|
shuffle(cores)
|
||||||
|
for force in [False, True]:
|
||||||
|
for core in cores:
|
||||||
|
try:
|
||||||
|
core.remove_core(force)
|
||||||
|
TestRun.fail(f"Removing inactive CAS device should be possible by "
|
||||||
|
f"'remove-inactive' command only but it worked with 'remove' "
|
||||||
|
f"command with force option set to {force}.")
|
||||||
|
except CmdException as e:
|
||||||
|
TestRun.LOGGER.info(f"Remove core operation is blocked for inactive CAS device "
|
||||||
|
f"as expected. Force option set to: {force}")
|
||||||
|
cli_messages.check_stderr_msg(
|
||||||
|
e.output, cli_messages.remove_inactive_core_with_remove_command)
|
||||||
|
output = casadm.list_caches().stdout
|
||||||
|
if core.path not in output:
|
||||||
|
TestRun.fail(
|
||||||
|
f"CAS device is not listed in casadm list output but it should be."
|
||||||
|
f"\n{output}")
|
||||||
|
|
||||||
|
with TestRun.step("Try removing CAS devices using remove-inactive command without ‘force’ "
|
||||||
|
"option. Verify that for dirty CAS devices operation is blocked, proper "
|
||||||
|
"message is displayed and device is still listed."):
|
||||||
shuffle(cores)
|
shuffle(cores)
|
||||||
for core in cores:
|
for core in cores:
|
||||||
try:
|
try:
|
||||||
dirty_blocks = core.get_dirty_blocks()
|
dirty_blocks = core.get_dirty_blocks()
|
||||||
core.remove_core()
|
core.remove_inactive()
|
||||||
if dirty_blocks != Size.zero():
|
if dirty_blocks != Size.zero():
|
||||||
TestRun.fail("Removing dirty CAS device should be impossible but remove "
|
TestRun.fail("Removing dirty inactive CAS device should be impossible without "
|
||||||
"command executed without any error.")
|
"force option but remove-inactive command executed without "
|
||||||
|
"any error.")
|
||||||
TestRun.LOGGER.info("Removing core with force option skipped for clean CAS device.")
|
TestRun.LOGGER.info("Removing core with force option skipped for clean CAS device.")
|
||||||
except CmdException as e:
|
except CmdException as e:
|
||||||
TestRun.LOGGER.info("Remove operation without force option is blocked for "
|
TestRun.LOGGER.info("Remove-inactive operation without force option is blocked for "
|
||||||
"dirty CAS device as expected.")
|
"dirty CAS device as expected.")
|
||||||
cli_messages.check_stderr_msg(e.output, cli_messages.remove_inactive_core)
|
cli_messages.check_stderr_msg(e.output, cli_messages.remove_inactive_dirty_core)
|
||||||
output = casadm.list_caches().stdout
|
output = casadm.list_caches().stdout
|
||||||
if core.path not in output:
|
if core.path not in output:
|
||||||
TestRun.fail(f"CAS device is not listed in casadm list output but it should be."
|
TestRun.fail(f"CAS device is not listed in casadm list output but it should be."
|
||||||
f"\n{output}")
|
f"\n{output}")
|
||||||
core.remove_core(force=True)
|
core.remove_inactive(force=True)
|
||||||
|
|
||||||
with TestRun.step("Plug missing disk and stop cache."):
|
with TestRun.step("Plug missing disk and stop cache."):
|
||||||
plug_device.plug()
|
plug_device.plug()
|
||||||
|
Loading…
Reference in New Issue
Block a user