You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-10-31 18:30:33 +03:00
Check dirs permissions only when not in container
This commit is contained in:
@@ -29,7 +29,7 @@ from cmapi_server.failover_agent import FailoverAgent
|
|||||||
from cmapi_server.managers.application import AppManager
|
from cmapi_server.managers.application import AppManager
|
||||||
from cmapi_server.managers.process import MCSProcessManager
|
from cmapi_server.managers.process import MCSProcessManager
|
||||||
from cmapi_server.managers.certificate import CertificateManager
|
from cmapi_server.managers.certificate import CertificateManager
|
||||||
from cmapi_server.state_checks import run_state_checks
|
from cmapi_server.invariant_checks import run_invariant_checks
|
||||||
from failover.node_monitor import NodeMonitor
|
from failover.node_monitor import NodeMonitor
|
||||||
from mcs_node_control.models.dbrm_socket import SOCK_TIMEOUT, DBRMSocketHandler
|
from mcs_node_control.models.dbrm_socket import SOCK_TIMEOUT, DBRMSocketHandler
|
||||||
from mcs_node_control.models.node_config import NodeConfig
|
from mcs_node_control.models.node_config import NodeConfig
|
||||||
@@ -153,7 +153,7 @@ if __name__ == '__main__':
|
|||||||
CertificateManager.renew_certificate()
|
CertificateManager.renew_certificate()
|
||||||
|
|
||||||
# Run checks, if some of them fail -- log and exit
|
# Run checks, if some of them fail -- log and exit
|
||||||
run_state_checks()
|
run_invariant_checks()
|
||||||
|
|
||||||
app = cherrypy.tree.mount(root=None, config=CMAPI_CONF_PATH)
|
app = cherrypy.tree.mount(root=None, config=CMAPI_CONF_PATH)
|
||||||
root_config = {
|
root_config = {
|
||||||
|
|||||||
95
cmapi/cmapi_server/invariant_checks.py
Normal file
95
cmapi/cmapi_server/invariant_checks.py
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from mr_kot import Runner, RunResult, Status, check, check_all, fact, parametrize
|
||||||
|
from mr_kot_fs_validators import GroupIs, HasMode, IsDir, OwnerIs
|
||||||
|
|
||||||
|
from cmapi_server import helpers
|
||||||
|
from cmapi_server.constants import MCS_DATA_PATH
|
||||||
|
from mcs_node_control.models.node_config import NodeConfig
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def run_invariant_checks() -> RunResult:
|
||||||
|
"""Run invariant checks, log warnings/errors/failures, and exit the process on failure/error.
|
||||||
|
"""
|
||||||
|
logger.info('Starting invariant checks')
|
||||||
|
try:
|
||||||
|
runner = Runner()
|
||||||
|
result = runner.run()
|
||||||
|
except Exception:
|
||||||
|
logger.exception('Got unexpected exception while checking invariants')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Log each fail/error/warning for diagnostics
|
||||||
|
for item in result.items:
|
||||||
|
if item.status in (Status.FAIL, Status.ERROR, Status.WARN):
|
||||||
|
fn = logger.warning if item.status == Status.WARN else logger.error
|
||||||
|
fn(
|
||||||
|
'Invariant check with id=%s produced %s: %r',
|
||||||
|
item.id, item.status, item.evidence,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info('Stats: overall=%s counts=%s', result.overall, {k.value: v for k, v in result.counts.items() if v != 0})
|
||||||
|
if result.overall in (Status.FAIL, Status.ERROR):
|
||||||
|
logger.error('Invariant checks failed, exiting')
|
||||||
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
logger.info('Invariant checks passed')
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
### Facts
|
||||||
|
|
||||||
|
@fact
|
||||||
|
def storage_type() -> str:
|
||||||
|
"""Provides storage type: shared_fs or s3."""
|
||||||
|
return 's3' if NodeConfig().s3_enabled() else 'shared_fs'
|
||||||
|
|
||||||
|
@fact
|
||||||
|
def is_shared_fs(storage_type: str) -> bool:
|
||||||
|
return storage_type == 'shared_fs'
|
||||||
|
|
||||||
|
@fact
|
||||||
|
def dispatcher_name() -> str:
|
||||||
|
"""Provides environment dispatcher name: systemd or container"""
|
||||||
|
cfg = helpers.get_config_parser()
|
||||||
|
name, _ = helpers.get_dispatcher_name_and_path(cfg)
|
||||||
|
return name
|
||||||
|
|
||||||
|
@fact
|
||||||
|
def is_systemd_disp(dispatcher_name: str) -> bool:
|
||||||
|
return dispatcher_name == 'systemd'
|
||||||
|
|
||||||
|
|
||||||
|
### Checks
|
||||||
|
|
||||||
|
REQUIRED_LOCAL_DIRS = [
|
||||||
|
os.path.join(MCS_DATA_PATH, 'data1'),
|
||||||
|
os.path.join(MCS_DATA_PATH, 'data1', 'systemFiles'),
|
||||||
|
os.path.join(MCS_DATA_PATH, 'data1', 'systemFiles', 'dbrm'),
|
||||||
|
]
|
||||||
|
|
||||||
|
@check(selector='is_shared_fs')
|
||||||
|
@parametrize('dir', values=REQUIRED_LOCAL_DIRS, fail_fast=True)
|
||||||
|
def required_dirs_perms(dir: str) -> tuple[Status, str]:
|
||||||
|
status, ev = check_all(
|
||||||
|
dir,
|
||||||
|
IsDir(),
|
||||||
|
HasMode('1755'),
|
||||||
|
)
|
||||||
|
return (status, ev)
|
||||||
|
|
||||||
|
@check(selector='is_shared_fs, is_systemd_disp')
|
||||||
|
@parametrize('dir', values=REQUIRED_LOCAL_DIRS, fail_fast=True)
|
||||||
|
def required_dirs_ownership(dir: str) -> tuple[Status, str]:
|
||||||
|
# Check ownership only when not in containers
|
||||||
|
status, ev = check_all(
|
||||||
|
dir,
|
||||||
|
OwnerIs('mysql'),
|
||||||
|
GroupIs('mysql'),
|
||||||
|
)
|
||||||
|
return (status, ev)
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
[tool.ruff]
|
|
||||||
line-length = 80
|
|
||||||
target-version = "py39"
|
|
||||||
# Enable common rule sets
|
|
||||||
select = [
|
|
||||||
"E", # pycodestyle errors
|
|
||||||
"F", # pyflakes: undefined names, unused imports, etc.
|
|
||||||
"I", # isort: import sorting
|
|
||||||
"B", # flake8-bugbear: common bugs and anti-patterns
|
|
||||||
"UP", # pyupgrade: use modern Python syntax
|
|
||||||
"N", # pep8-naming: naming conventions
|
|
||||||
]
|
|
||||||
|
|
||||||
ignore = []
|
|
||||||
|
|
||||||
# Exclude cache and temporary directories
|
|
||||||
exclude = [
|
|
||||||
"__pycache__",
|
|
||||||
]
|
|
||||||
|
|
||||||
[tool.ruff.format]
|
|
||||||
quote-style = "single"
|
|
||||||
|
|
||||||
[tool.ruff.lint.isort]
|
|
||||||
force-single-line = false
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from mcs_node_control.models.node_config import NodeConfig
|
|
||||||
from mr_kot import Status, check, check_all, fact, parametrize
|
|
||||||
from mr_kot.runner import Runner, RunResult
|
|
||||||
from mr_kot_fs_validators import GroupIs, HasMode, IsDir, OwnerIs
|
|
||||||
|
|
||||||
from cmapi_server.constants import MCS_DATA_PATH
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
def run_state_checks(*, verbose: bool = False) -> RunResult:
|
|
||||||
"""Run state checks, log warnings/errors/failures, and exit the process on failure/error.
|
|
||||||
"""
|
|
||||||
logger.info("Starting invariant checks")
|
|
||||||
try:
|
|
||||||
runner = Runner(verbose=verbose, include_tags=True)
|
|
||||||
result = runner.run()
|
|
||||||
except Exception:
|
|
||||||
logger.exception('Unexpected exception during state checks')
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# Log each fail/error/warning for diagnostics
|
|
||||||
for item in result.items:
|
|
||||||
if item.status in (Status.FAIL, Status.ERROR, Status.WARN):
|
|
||||||
logger.error(
|
|
||||||
'State check with id=%s produced %s: %r',
|
|
||||||
item.id, item.status, item.evidence,
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.info('Stats: overall=%s counts=%s', result.overall, {k.value: v for k, v in result.counts.items() if v != 0})
|
|
||||||
if result.overall in (Status.FAIL, Status.ERROR):
|
|
||||||
logger.error('State check failed, exiting')
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
@fact
|
|
||||||
def storage_type() -> str:
|
|
||||||
"""Provides storage type: shared_fs or s3."""
|
|
||||||
return 's3' if NodeConfig().s3_enabled() else 'shared_fs'
|
|
||||||
|
|
||||||
@fact
|
|
||||||
def is_shared_fs(storage_type: str) -> bool:
|
|
||||||
return storage_type == 'shared_fs'
|
|
||||||
|
|
||||||
@check(selector='is_shared_fs')
|
|
||||||
@parametrize(
|
|
||||||
'required_local_dir',
|
|
||||||
values=[
|
|
||||||
os.path.join(MCS_DATA_PATH, 'data1'),
|
|
||||||
os.path.join(MCS_DATA_PATH, 'data1', 'systemFiles'),
|
|
||||||
os.path.join(MCS_DATA_PATH, 'data1', 'systemFiles', 'dbrm'),
|
|
||||||
],
|
|
||||||
fail_fast=True,
|
|
||||||
)
|
|
||||||
def required_dirs_fs_state(required_local_dir: str) -> tuple[Status, str]:
|
|
||||||
status, ev = check_all(
|
|
||||||
required_local_dir,
|
|
||||||
IsDir(),
|
|
||||||
HasMode('1755'),
|
|
||||||
OwnerIs('mysql'),
|
|
||||||
GroupIs('mysql'),
|
|
||||||
)
|
|
||||||
return (status, ev)
|
|
||||||
@@ -23,6 +23,7 @@ exclude = [
|
|||||||
quote-style = "single"
|
quote-style = "single"
|
||||||
|
|
||||||
[tool.ruff.lint.isort]
|
[tool.ruff.lint.isort]
|
||||||
|
known-first-party = ["cmapi_server", "failover", "mcs_node_control", "tracing"]
|
||||||
force-single-line = false
|
force-single-line = false
|
||||||
combine-as-imports = true
|
combine-as-imports = true
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,6 @@ Routes==2.5.1
|
|||||||
typer==0.15.2
|
typer==0.15.2
|
||||||
pydantic==2.11.7
|
pydantic==2.11.7
|
||||||
sentry-sdk==2.34.1
|
sentry-sdk==2.34.1
|
||||||
# State checks
|
# Invariant checks
|
||||||
mr_kot==0.8.1
|
mr_kot==0.8.3
|
||||||
mr_kot_fs_validators==0.1.0
|
mr_kot_fs_validators==0.1.0
|
||||||
@@ -144,7 +144,7 @@ more-itertools==10.7.0
|
|||||||
# cherrypy
|
# cherrypy
|
||||||
# jaraco-functools
|
# jaraco-functools
|
||||||
# jaraco-text
|
# jaraco-text
|
||||||
mr-kot==0.8.1
|
mr-kot==0.8.3
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
mr-kot-fs-validators==0.1.0
|
mr-kot-fs-validators==0.1.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
|
|||||||
Reference in New Issue
Block a user