1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-11-02 06:13:16 +03:00
Files
mariadb-columnstore-engine/cmapi/cmapi_server/controllers/request_models.py
mariadb-AlanMologorsky c86586c228 feat(cmapi,failover): MCOL-6006 Disable failover when shared storage not detected
- Add SharedStorageMonitor thread to periodically verify shared storage:
  * Writes a temp file to the shared location and validates MD5 from all nodes.
  * Skips nodes with unstable recent heartbeats; retries once; defers decision if any node is unreachable.
  * Updates a cluster-wide stateful flag (shared_storage_on) only on conclusive checks.
- New CMAPI endpoints:
  * PUT /cmapi/{ver}/cluster/check-shared-storage — orchestrates cross-node checks.
  * GET /cmapi/{ver}/node/check-shared-file — validates a given file’s MD5 on a node.
  * PUT /cmapi/{ver}/node/stateful-config — fast path to distribute stateful config updates.
- Introduce in-memory stateful config (AppStatefulConfig) with versioned flags (term/seq) and shared_storage_on flag:
  * Broadcast via helpers.broadcast_stateful_config and enhanced broadcast_new_config.
  * Config PUT is now validated with Pydantic models; supports stateful-only updates and set_mode requests.
- Failover behavior:
  * NodeMonitor keeps failover inactive when shared_storage_on is false or cluster size < 3.
  * Rebalancing DBRoots becomes a no-op when shared storage is OFF (safety guard).
- mcl status improvements: per-node 'state' (online/offline), better timeouts and error reporting.
- Routing/wiring: add dispatcher routes for new endpoints; add ClusterModeEnum.
- Tests: cover shared-storage monitor (unreachable nodes, HB-based skipping), node manipulation with shared storage ON/OFF, and server/config flows.
- Dependencies: add pydantic; minor cleanups and logging.
2025-10-01 21:10:34 +04:00

66 lines
1.9 KiB
Python

from typing import Annotated, Optional, Union, Literal
from pydantic import BaseModel, Discriminator, RootModel, Tag
from cmapi_server.constants import (
DEFAULT_MCS_CONF_PATH, DEFAULT_SM_CONF_PATH, ClusterModeEnum,
)
from cmapi_server.managers.application import StatefulConfigModel
class BaseConfigPutRequestModel(BaseModel):
timeout: int
test: Optional[bool] = False
class BaseFullStatefulConfigPutRequestModel(BaseConfigPutRequestModel):
only_stateful_config: Optional[bool] = False
stateful_config_dict: StatefulConfigModel
class StatefulConfigPutRequestModel(BaseFullStatefulConfigPutRequestModel):
type: Literal['stateful'] = 'stateful'
class PutConfigSetModeRequestModel(BaseConfigPutRequestModel):
type: Literal['set_mode'] = 'set_mode'
revision: str
manager: str
cluster_mode: ClusterModeEnum
class FullConfigPutRequestModel(BaseFullStatefulConfigPutRequestModel):
type: Literal['full'] = 'full'
revision: str
manager: str
cluster_mode: Optional[str] = None
config: Optional[str] = None
sm_config: Optional[str] = None
mcs_config_filename: Optional[str] = DEFAULT_MCS_CONF_PATH
sm_config_filename: Optional[str] = DEFAULT_SM_CONF_PATH
secrets: Optional[dict] = None
def get_discriminator_value(data: dict) -> str:
"""Custom discriminator function for ConfigRequest union."""
if data.get('cluster_mode') is not None:
return 'set_mode'
if data.get('only_stateful_config', False):
return 'stateful'
return 'full'
class ConfigPutRequestRootModel(
RootModel[
Annotated[
Union[
Annotated[StatefulConfigPutRequestModel, Tag('stateful')],
Annotated[PutConfigSetModeRequestModel, Tag('set_mode')],
Annotated[FullConfigPutRequestModel, Tag('full')]
],
Discriminator(get_discriminator_value),
]
]
):
pass