frostfs-testlib/src/frostfs_testlib/storage/dataclasses/node_base.py
Andrey Berezin 2240be09d2 Add repr and str for most classes used in parametrize
Signed-off-by: Andrey Berezin <a.berezin@yadro.com>
2023-07-24 19:34:21 +03:00

146 lines
4.1 KiB
Python

from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Optional, Tuple, TypedDict, TypeVar
import yaml
from frostfs_testlib.hosting.config import ServiceConfig
from frostfs_testlib.hosting.interfaces import Host
from frostfs_testlib.storage.constants import ConfigAttributes
from frostfs_testlib.testing.readable import HumanReadableABC
from frostfs_testlib.utils import wallet_utils
@dataclass
class NodeBase(HumanReadableABC):
"""
Represents a node of some underlying service
"""
id: str
name: str
host: Host
_process_name: str
def __init__(self, id, name, host) -> None:
self.id = id
self.name = name
self.host = host
self.construct()
def construct(self):
pass
def __eq__(self, other):
return self.name == other.name
def __hash__(self):
return id(self.name)
def __str__(self):
return self.label
def __repr__(self) -> str:
return self.label
@property
def label(self) -> str:
return self.name
def get_service_systemctl_name(self) -> str:
return self._get_attribute(ConfigAttributes.SERVICE_NAME)
def get_process_name(self) -> str:
return self._process_name
def start_service(self):
self.host.start_service(self.name)
@abstractmethod
def service_healthcheck(self) -> bool:
"""Service healthcheck."""
def stop_service(self):
self.host.stop_service(self.name)
def restart_service(self):
self.host.restart_service(self.name)
def get_wallet_password(self) -> str:
return self._get_attribute(ConfigAttributes.WALLET_PASSWORD)
def get_wallet_path(self) -> str:
return self._get_attribute(
ConfigAttributes.LOCAL_WALLET_PATH,
ConfigAttributes.WALLET_PATH,
)
def get_remote_wallet_path(self) -> str:
"""
Returns node wallet file path located on remote host
"""
return self._get_attribute(
ConfigAttributes.WALLET_PATH,
)
def get_remote_config_path(self) -> str:
"""
Returns node config file path located on remote host
"""
return self._get_attribute(
ConfigAttributes.CONFIG_PATH,
)
def get_wallet_config_path(self) -> str:
return self._get_attribute(
ConfigAttributes.LOCAL_WALLET_CONFIG,
ConfigAttributes.WALLET_CONFIG,
)
def get_config(self) -> Tuple[str, dict]:
config_file_path = self._get_attribute(ConfigAttributes.CONFIG_PATH)
shell = self.host.get_shell()
result = shell.exec(f"cat {config_file_path}")
config_text = result.stdout
config = yaml.safe_load(config_text)
return config_file_path, config
def save_config(self, new_config: dict) -> None:
config_file_path = self._get_attribute(ConfigAttributes.CONFIG_PATH)
shell = self.host.get_shell()
config_str = yaml.dump(new_config)
shell.exec(f"echo '{config_str}' | sudo tee {config_file_path}")
def get_wallet_public_key(self):
storage_wallet_path = self.get_wallet_path()
storage_wallet_pass = self.get_wallet_password()
return wallet_utils.get_wallet_public_key(storage_wallet_path, storage_wallet_pass)
def _get_attribute(
self, attribute_name: str, default_attribute_name: Optional[str] = None
) -> str:
config = self.host.get_service_config(self.name)
if attribute_name not in config.attributes:
if default_attribute_name is None:
raise RuntimeError(
f"Service {self.name} has no {attribute_name} in config and fallback attribute isn't set either"
)
return config.attributes[default_attribute_name]
return config.attributes[attribute_name]
def _get_service_config(self) -> ServiceConfig:
return self.host.get_service_config(self.name)
ServiceClass = TypeVar("ServiceClass", bound=NodeBase)
class NodeClassDict(TypedDict):
hosting_service_name: str
cls: type[NodeBase]