-
Notifications
You must be signed in to change notification settings - Fork 77
MCOL-5861 cmapi read only nodes #3432
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: stable-23.10
Are you sure you want to change the base?
Changes from all commits
37453ad
9a1ac0e
93cd935
fbf4844
3671d49
1714bef
7255340
04015ae
245cceb
7199c97
ff25d4e
5359c98
e7fd6fc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -104,7 +104,8 @@ def enable_console_logging(logger: logging.Logger) -> None: | |
def config_cmapi_server_logging(): | ||
# add custom level TRACE only for develop purposes | ||
# could be activated using API endpoints or cli tool without relaunching | ||
add_logging_level('TRACE', 5) | ||
if not hasattr(logging, 'TRACE'): | ||
add_logging_level('TRACE', 5) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. JFYI I think to remove or rewrite this dev function. |
||
cherrypy._cplogging.LogManager.error = custom_cherrypy_error | ||
# reconfigure cherrypy.access log message format | ||
# Default access_log_format '{h} {l} {u} {t} "{r}" {s} {b} "{f}" "{a}"' | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,8 @@ | |
import psutil | ||
|
||
from cmapi_server.exceptions import CMAPIBasicError | ||
from cmapi_server.constants import MCS_INSTALL_BIN, ALL_MCS_PROGS | ||
from cmapi_server.constants import MCS_INSTALL_BIN, ALL_MCS_PROGS, MCSProgs, ProgInfo | ||
from cmapi_server.process_dispatchers.base import BaseDispatcher | ||
from cmapi_server.process_dispatchers.systemd import SystemdDispatcher | ||
from cmapi_server.process_dispatchers.container import ( | ||
ContainerDispatcher | ||
|
@@ -18,7 +19,7 @@ | |
from mcs_node_control.models.process import Process | ||
|
||
|
||
PROCESS_DISPATCHERS = { | ||
PROCESS_DISPATCHERS: dict[str, type[BaseDispatcher]] = { | ||
'systemd': SystemdDispatcher, | ||
# could be used in docker containers and OSes w/o systemd | ||
'container': ContainerDispatcher, | ||
|
@@ -32,10 +33,10 @@ class MCSProcessManager: | |
e.g. re/-start or stop systemd services, run executable. | ||
""" | ||
CONTROLLER_MAX_RETRY = 30 | ||
mcs_progs = {} | ||
mcs_progs: dict[str, ProgInfo] = {} | ||
mcs_version_info = None | ||
dispatcher_name = None | ||
process_dispatcher = None | ||
process_dispatcher: BaseDispatcher = None | ||
|
||
@classmethod | ||
def _get_prog_name(cls, name: str) -> str: | ||
|
@@ -47,12 +48,13 @@ def _get_prog_name(cls, name: str) -> str: | |
:rtype: str | ||
""" | ||
if cls.dispatcher_name == 'systemd': | ||
return ALL_MCS_PROGS[name].service_name | ||
prog = MCSProgs(name) | ||
return ALL_MCS_PROGS[prog].service_name | ||
return name | ||
|
||
@classmethod | ||
def _get_sorted_progs( | ||
cls, is_primary: bool, reverse: bool = False | ||
cls, is_primary: bool, reverse: bool = False, is_read_only: bool = False | ||
) -> dict: | ||
"""Get sorted services dict. | ||
|
||
|
@@ -72,6 +74,13 @@ def _get_sorted_progs( | |
for prog_name, prog_info in cls.mcs_progs.items() | ||
if prog_name not in PRIMARY_PROGS | ||
} | ||
|
||
if is_read_only: | ||
logging.debug('Node is in read-only mode, skipping WriteEngine') | ||
unsorted_progs.pop( | ||
MCSProgs.WRITE_ENGINE_SERVER.value, None | ||
) | ||
|
||
if reverse: | ||
# stop sequence builds using stop_priority property | ||
return dict( | ||
|
@@ -89,7 +98,8 @@ def _detect_processes(cls) -> None: | |
if cls.mcs_progs: | ||
logging.warning('Mcs ProcessHandler already detected processes.') | ||
|
||
for prog_name, prog_info in ALL_MCS_PROGS.items(): | ||
for prog, prog_info in ALL_MCS_PROGS.items(): | ||
prog_name = prog.value | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. JFYI It's what I mentioned before here about naming and access names. prog.value == prog_name. It's somehow confusing. |
||
if os.path.exists(os.path.join(MCS_INSTALL_BIN, prog_name)): | ||
cls.mcs_progs[prog_name] = prog_info | ||
|
||
|
@@ -404,37 +414,47 @@ def is_node_processes_ok( | |
return set(node_progs) == set(p['name'] for p in running_procs) | ||
|
||
@classmethod | ||
def start_node(cls, is_primary: bool, use_sudo: bool = True): | ||
def start_node( | ||
cls, | ||
is_primary: bool, | ||
use_sudo: bool = True, | ||
is_read_only: bool = False, | ||
) -> None: | ||
"""Start mcs node processes. | ||
|
||
:param is_primary: is node primary or not, defaults to True | ||
:type is_primary: bool | ||
:param use_sudo: use sudo or not, defaults to True | ||
:type use_sudo: bool, optional | ||
:param is_read_only: if true, doesn't start WriteEngine | ||
:type is_read_only: bool, optional | ||
:raises CMAPIBasicError: immediately if one mcs process not started | ||
""" | ||
for prog_name in cls._get_sorted_progs(is_primary): | ||
for prog_name in cls._get_sorted_progs(is_primary=is_primary, is_read_only=is_read_only): | ||
if ( | ||
cls.dispatcher_name == 'systemd' | ||
and prog_name == 'StorageManager' | ||
and prog_name == MCSProgs.STORAGE_MANAGER.value | ||
): | ||
# TODO: MCOL-5458 | ||
logging.info( | ||
f'Skip starting {prog_name} with systemd dispatcher.' | ||
) | ||
continue | ||
# TODO: additional error handling | ||
if prog_name == 'controllernode': | ||
if prog_name == MCSProgs.CONTROLLER_NODE.value: | ||
cls._wait_for_workernodes() | ||
if prog_name in ('DMLProc', 'DDLProc'): | ||
if prog_name in (MCSProgs.DML_PROC.value, MCSProgs.DDL_PROC.value): | ||
cls._wait_for_controllernode() | ||
if not cls.start(prog_name, is_primary, use_sudo): | ||
logging.error(f'Process "{prog_name}" not started properly.') | ||
raise CMAPIBasicError(f'Error while starting "{prog_name}".') | ||
|
||
@classmethod | ||
def stop_node( | ||
cls, is_primary: bool, use_sudo: bool = True, timeout: int = 10 | ||
cls, | ||
is_primary: bool, | ||
use_sudo: bool = True, | ||
timeout: int = 10, | ||
): | ||
"""Stop mcs node processes. | ||
|
||
|
@@ -450,14 +470,14 @@ def stop_node( | |
# so use full available list of processes. Otherwise, it could cause | ||
# undefined behaviour when primary gone and then recovers (failover | ||
# triggered 2 times). | ||
for prog_name in cls._get_sorted_progs(True, reverse=True): | ||
for prog_name in cls._get_sorted_progs(is_primary=True, reverse=True): | ||
if not cls.stop(prog_name, is_primary, use_sudo): | ||
logging.error(f'Process "{prog_name}" not stopped properly.') | ||
raise CMAPIBasicError(f'Error while stopping "{prog_name}"') | ||
|
||
@classmethod | ||
def restart_node(cls, is_primary: bool, use_sudo: bool): | ||
def restart_node(cls, is_primary: bool, use_sudo: bool, is_read_only: bool = False): | ||
"""TODO: For next releases.""" | ||
if cls.get_running_mcs_procs(): | ||
cls.stop_node(is_primary, use_sudo) | ||
cls.start_node(is_primary, use_sudo) | ||
cls.start_node(is_primary, use_sudo, is_read_only) | ||
mariadb-AlexanderPresniakov marked this conversation as resolved.
Show resolved
Hide resolved
|
Uh oh!
There was an error while loading. Please reload this page.