Add mask/unmask for services #104
5 changed files with 45 additions and 69 deletions
|
@ -126,6 +126,14 @@ class DockerHost(Host):
|
|||
timeout=service_attributes.stop_timeout,
|
||||
)
|
||||
|
||||
def mask_service(self, service_name: str) -> None:
|
||||
# Not required for Docker
|
||||
return
|
||||
|
||||
def unmask_service(self, service_name: str) -> None:
|
||||
# Not required for Docker
|
||||
return
|
||||
|
||||
def wait_success_suspend_process(self, service_name: str):
|
||||
raise NotImplementedError("Not supported for docker")
|
||||
|
||||
|
|
|
@ -118,6 +118,26 @@ class Host(ABC):
|
|||
service_name: Name of the service to stop.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def mask_service(self, service_name: str) -> None:
|
||||
"""Prevent the service from start by any activity by masking it.
|
||||
|
||||
The service must be hosted on this host.
|
||||
|
||||
Args:
|
||||
service_name: Name of the service to mask.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def unmask_service(self, service_name: str) -> None:
|
||||
"""Allow the service to start by any activity by unmasking it.
|
||||
|
||||
The service must be hosted on this host.
|
||||
|
||||
Args:
|
||||
service_name: Name of the service to unmask.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def restart_service(self, service_name: str) -> None:
|
||||
"""Restarts the service with specified name and waits until it starts.
|
||||
|
|
|
@ -15,8 +15,7 @@ from frostfs_testlib.resources.cli import (
|
|||
)
|
||||
from frostfs_testlib.resources.common import MORPH_BLOCK_TIME
|
||||
from frostfs_testlib.shell import Shell
|
||||
from frostfs_testlib.steps.epoch import tick_epoch
|
||||
from frostfs_testlib.steps.epoch import wait_for_epochs_align
|
||||
from frostfs_testlib.steps.epoch import tick_epoch, wait_for_epochs_align
|
||||
from frostfs_testlib.storage.cluster import Cluster, StorageNode
|
||||
from frostfs_testlib.storage.dataclasses.frostfs_services import S3Gate
|
||||
from frostfs_testlib.utils import datetime_utils
|
||||
|
@ -41,44 +40,6 @@ class HealthStatus:
|
|||
return HealthStatus(network, health)
|
||||
|
||||
|
||||
@reporter.step_deco("Stop random storage nodes")
|
||||
def stop_random_storage_nodes(number: int, nodes: list[StorageNode]) -> list[StorageNode]:
|
||||
"""
|
||||
Shuts down the given number of randomly selected storage nodes.
|
||||
Args:
|
||||
number: the number of storage nodes to stop
|
||||
nodes: the list of storage nodes to stop
|
||||
Returns:
|
||||
the list of nodes that were stopped
|
||||
"""
|
||||
nodes_to_stop = random.sample(nodes, number)
|
||||
for node in nodes_to_stop:
|
||||
node.stop_service()
|
||||
return nodes_to_stop
|
||||
|
||||
|
||||
@reporter.step_deco("Start storage node")
|
||||
def start_storage_nodes(nodes: list[StorageNode]) -> None:
|
||||
"""
|
||||
The function starts specified storage nodes.
|
||||
Args:
|
||||
nodes: the list of nodes to start
|
||||
"""
|
||||
for node in nodes:
|
||||
node.start_service()
|
||||
|
||||
|
||||
@reporter.step_deco("Stop storage node")
|
||||
def stop_storage_nodes(nodes: list[StorageNode]) -> None:
|
||||
"""
|
||||
The function starts specified storage nodes.
|
||||
Args:
|
||||
nodes: the list of nodes to start
|
||||
"""
|
||||
for node in nodes:
|
||||
node.stop_service()
|
||||
|
||||
|
||||
@reporter.step_deco("Get Locode from random storage node")
|
||||
def get_locode_from_random_node(cluster: Cluster) -> str:
|
||||
node = random.choice(cluster.services(StorageNode))
|
||||
|
@ -329,25 +290,3 @@ def _run_control_command(node: StorageNode, command: str) -> None:
|
|||
f"--wallet {wallet_path} --config {wallet_config_path}"
|
||||
)
|
||||
return result.stdout
|
||||
|
||||
|
||||
@reporter.step_deco("Start services s3gate ")
|
||||
def start_s3gates(cluster: Cluster) -> None:
|
||||
"""
|
||||
The function starts specified storage nodes.
|
||||
Args:
|
||||
cluster: cluster instance under test
|
||||
"""
|
||||
for gate in cluster.services(S3Gate):
|
||||
gate.start_service()
|
||||
|
||||
|
||||
@reporter.step_deco("Stop services s3gate ")
|
||||
def stop_s3gates(cluster: Cluster) -> None:
|
||||
"""
|
||||
The function starts specified storage nodes.
|
||||
Args:
|
||||
cluster: cluster instance under test
|
||||
"""
|
||||
for gate in cluster.services(S3Gate):
|
||||
gate.stop_service()
|
||||
|
|
|
@ -135,9 +135,9 @@ class ClusterStateController:
|
|||
|
||||
@run_optionally(optionals.OPTIONAL_FAILOVER_ENABLED)
|
||||
@reporter.step_deco("Stop storage service on {node}")
|
||||
def stop_storage_service(self, node: ClusterNode):
|
||||
def stop_storage_service(self, node: ClusterNode, mask: bool = True):
|
||||
self.stopped_storage_nodes.append(node)
|
||||
node.storage_node.stop_service()
|
||||
node.storage_node.stop_service(mask)
|
||||
|
||||
@run_optionally(optionals.OPTIONAL_FAILOVER_ENABLED)
|
||||
@reporter.step_deco("Stop all {service_type} services")
|
||||
|
@ -171,9 +171,11 @@ class ClusterStateController:
|
|||
|
||||
@run_optionally(optionals.OPTIONAL_FAILOVER_ENABLED)
|
||||
@reporter.step_deco("Stop {service_type} service on {node}")
|
||||
def stop_service_of_type(self, node: ClusterNode, service_type: type[ServiceClass]):
|
||||
def stop_service_of_type(
|
||||
self, node: ClusterNode, service_type: type[ServiceClass], mask: bool = True
|
||||
):
|
||||
service = node.service(service_type)
|
||||
service.stop_service()
|
||||
service.stop_service(mask)
|
||||
self.stopped_services.add(service)
|
||||
|
||||
@run_optionally(optionals.OPTIONAL_FAILOVER_ENABLED)
|
||||
|
@ -207,8 +209,8 @@ class ClusterStateController:
|
|||
|
||||
@run_optionally(optionals.OPTIONAL_FAILOVER_ENABLED)
|
||||
@reporter.step_deco("Stop s3 gate on {node}")
|
||||
def stop_s3_gate(self, node: ClusterNode):
|
||||
node.s3_gate.stop_service()
|
||||
def stop_s3_gate(self, node: ClusterNode, mask: bool = True):
|
||||
node.s3_gate.stop_service(mask)
|
||||
self.stopped_s3_gates.append(node)
|
||||
|
||||
@run_optionally(optionals.OPTIONAL_FAILOVER_ENABLED)
|
||||
|
|
|
@ -57,6 +57,9 @@ class NodeBase(HumanReadableABC):
|
|||
return self._process_name
|
||||
|
||||
def start_service(self):
|
||||
with reporter.step(f"Unmask {self.name} service on {self.host.config.address}"):
|
||||
self.host.unmask_service(self.name)
|
||||
|
||||
with reporter.step(f"Start {self.name} service on {self.host.config.address}"):
|
||||
self.host.start_service(self.name)
|
||||
|
||||
|
@ -67,7 +70,11 @@ class NodeBase(HumanReadableABC):
|
|||
def get_metrics_endpoint(self) -> str:
|
||||
return self._get_attribute(ConfigAttributes.ENDPOINT_PROMETHEUS)
|
||||
|
||||
def stop_service(self):
|
||||
def stop_service(self, mask: bool = True):
|
||||
if mask:
|
||||
with reporter.step(f"Mask {self.name} service on {self.host.config.address}"):
|
||||
self.host.mask_service(self.name)
|
||||
|
||||
with reporter.step(f"Stop {self.name} service on {self.host.config.address}"):
|
||||
self.host.stop_service(self.name)
|
||||
|
||||
|
|
Loading…
Reference in a new issue