[#114] Add yaml configuration controllers

Signed-off-by: Andrey Berezin <a.berezin@yadro.com>
This commit is contained in:
Andrey Berezin 2023-11-10 22:43:13 +03:00 committed by Andrey Berezin
parent f8562da7e0
commit 72bd467c53
9 changed files with 244 additions and 22 deletions

View file

@ -1,8 +1,10 @@
import datetime
import time
from typing import TypeVar
import frostfs_testlib.resources.optionals as optionals
from frostfs_testlib.healthcheck.interfaces import Healthcheck
from frostfs_testlib.plugins import load_all
from frostfs_testlib.reporter import get_reporter
from frostfs_testlib.shell import CommandOptions, Shell, SshConnectionProvider
from frostfs_testlib.steps.network import IfUpDownHelper, IpTablesHelper
@ -22,6 +24,14 @@ reporter = get_reporter()
if_up_down_helper = IfUpDownHelper()
class StateManager:
def __init__(self, cluster_state_controller: "ClusterStateController") -> None:
self.csc = cluster_state_controller
StateManagerClass = TypeVar("StateManagerClass", bound=StateManager)
class ClusterStateController:
def __init__(self, shell: Shell, cluster: Cluster, healthcheck: Healthcheck) -> None:
self.stopped_nodes: list[ClusterNode] = []
@ -33,6 +43,18 @@ class ClusterStateController:
self.shell = shell
self.suspended_services: dict[str, list[ClusterNode]] = {}
self.nodes_with_modified_interface: list[ClusterNode] = []
self.managers: list[StateManagerClass] = []
# TODO: move all functionality to managers
managers = set(load_all(group="frostfs.testlib.csc_managers"))
for manager in managers:
self.managers.append(manager(self))
def manager(self, manager_type: type[StateManagerClass]) -> StateManagerClass:
for manager in self.managers:
# Subclasses here for the future if we have overriding subclasses of base interface
if issubclass(type(manager), manager_type):
return manager
def _get_stopped_by_node(self, node: ClusterNode) -> set[NodeBase]:
stopped_by_node = [svc for svc in self.stopped_services if svc.host == node.host]

View file

@ -0,0 +1,51 @@
from typing import Any
from frostfs_testlib.reporter import get_reporter
from frostfs_testlib.storage.cluster import ClusterNode
from frostfs_testlib.storage.controllers.cluster_state_controller import ClusterStateController, StateManager
from frostfs_testlib.storage.dataclasses.node_base import ServiceClass
from frostfs_testlib.testing import parallel
reporter = get_reporter()
class ConfigStateManager(StateManager):
def __init__(self, cluster_state_controller: ClusterStateController) -> None:
super().__init__(cluster_state_controller)
self.services_with_changed_config: set[tuple[ClusterNode, ServiceClass]] = set()
self.cluster = self.csc.cluster
@reporter.step_deco("Change configuration for {service_type} on all nodes")
def set_on_all_nodes(self, service_type: type[ServiceClass], values: dict[str, Any]):
services = self.cluster.services(service_type)
nodes = self.cluster.nodes(services)
self.services_with_changed_config.update([(node, service_type) for node in nodes])
self.csc.stop_services_of_type(service_type)
parallel([node.config(service_type).set for node in nodes], values=values)
self.csc.start_services_of_type(service_type)
@reporter.step_deco("Change configuration for {service_type} on {node}")
def set_on_node(self, node: ClusterNode, service_type: type[ServiceClass], values: dict[str, Any]):
self.services_with_changed_config.add((node, service_type))
self.csc.stop_service_of_type(node, service_type)
node.config(service_type).set(values)
self.csc.start_service_of_type(node, service_type)
@reporter.step_deco("Revert all configuration changes")
def revert_all(self):
if not self.services_with_changed_config:
return
parallel(self._revert_svc, self.services_with_changed_config)
self.services_with_changed_config.clear()
self.csc.start_all_stopped_services()
# TODO: parallel can't have multiple parallel_items :(
@reporter.step_deco("Revert all configuration {node_and_service}")
def _revert_svc(self, node_and_service: tuple[ClusterNode, ServiceClass]):
node, service_type = node_and_service
self.csc.stop_service_of_type(node, service_type)
node.config(service_type).revert()