1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2026-10-23 21:49:05 +03:00

feat(mcs, install_es): MCOL-6520 Add check MDB plugins precheck into Install_es.

This commit is contained in:
mariadb-AlanMologorsky
2026-09-03 16:27:29 +03:00
parent fb425157eb
commit f8c9bff109
2 changed files with 158 additions and 2 deletions

View File

@@ -1,10 +1,61 @@
import logging
import re
import shlex
from typing import Dict, List, Tuple
from cmapi_server.exceptions import CMAPIBasicError
from cmapi_server.constants import DEFAULT_MCS_CONF_PATH
from cmapi_server.exceptions import CEJError, CMAPIBasicError
from cmapi_server.helpers import get_cej_info
from mcs_node_control.models.node_config import NodeConfig
from cmapi_server.process_dispatchers.base import BaseDispatcher
# Registry of MariaDB plugins that the install_es auto-upgrader does NOT
# handle. If any of these are ACTIVE on the local node the precheck aborts
# the upgrade and instructs the operator how to proceed manually.
#
# Keys are compared case-insensitively against PLUGIN_NAME as reported by
# information_schema.PLUGINS. Currently focused on external storage engines
# shipped as separate mariadb-plugin-* packages; extend as needed.
UNSUPPORTED_PLUGINS_AUTOUPGRADE: Dict[str, str] = {
'SPIDER': (
"UNINSTALL SONAME 'ha_spider.so'; stop MariaDB; upgrade the "
"mariadb-plugin-spider package to a version matching the target "
"ES release; start MariaDB; INSTALL SONAME 'ha_spider.so'."
),
'CONNECT': (
"UNINSTALL SONAME 'ha_connect.so'; stop MariaDB; upgrade the "
"mariadb-plugin-connect package to a version matching the target "
"ES release; start MariaDB; INSTALL SONAME 'ha_connect.so'."
),
'SPHINX': (
"UNINSTALL SONAME 'ha_sphinx.so'; stop MariaDB; upgrade the "
"mariadb-plugin-sphinx package to a version matching the target "
"ES release; start MariaDB; INSTALL SONAME 'ha_sphinx.so'."
),
'OQGRAPH': (
"UNINSTALL SONAME 'ha_oqgraph.so'; stop MariaDB; upgrade the "
"mariadb-plugin-oqgraph package to a version matching the target "
"ES release; start MariaDB; INSTALL SONAME 'ha_oqgraph.so'."
),
'MROONGA': (
"UNINSTALL SONAME 'ha_mroonga.so'; stop MariaDB; upgrade the "
"mariadb-plugin-mroonga package to a version matching the target "
"ES release; start MariaDB; INSTALL SONAME 'ha_mroonga.so'."
),
'ROCKSDB': (
"UNINSTALL SONAME 'ha_rocksdb.so'; stop MariaDB; upgrade the "
"mariadb-plugin-rocksdb package to a version matching the target "
"ES release; start MariaDB; INSTALL SONAME 'ha_rocksdb.so'."
),
'S3': (
"UNINSTALL SONAME 'ha_s3.so'; stop MariaDB; upgrade the "
"mariadb-plugin-s3 package to a version matching the target ES "
"release; start MariaDB; INSTALL SONAME 'ha_s3.so'."
),
}
class PreInstallManager:
@staticmethod
@@ -52,3 +103,96 @@ class PreInstallManager:
)
logging.error(message)
raise CMAPIBasicError(message)
@staticmethod
def _get_active_plugins(
config: str = DEFAULT_MCS_CONF_PATH,
) -> List[Tuple[str, str]]:
"""Return list of ACTIVE plugins on the local MariaDB node.
Uses CrossEngineSupport credentials from Columnstore.xml (same as
`helpers.system_ready`). Plugin registration is stored in the
mysql.plugin system table so a single-node query is sufficient
for a Columnstore cluster (mysql.plugin is server-local, but
Columnstore cluster nodes share plugin state via replication or
identical package layout by convention).
:return: list of (PLUGIN_NAME, PLUGIN_TYPE) tuples
:raises CMAPIBasicError: if the query cannot be executed
"""
nc = NodeConfig()
root = nc.get_current_config_root(config)
try:
host, port, username, password = get_cej_info(root)
except CEJError as exc:
raise CMAPIBasicError(
'Cannot detect installed MariaDB plugins: '
'CrossEngineSupport credentials are missing or invalid. '
f'Details: {exc}'
) from exc
query = (
"SELECT PLUGIN_NAME, PLUGIN_TYPE "
"FROM information_schema.PLUGINS "
"WHERE PLUGIN_STATUS='ACTIVE';"
)
cmd = (
f'/usr/bin/mariadb -h {shlex.quote(host)} '
f'-P {shlex.quote(str(port))} '
f'-u {shlex.quote(username)} '
f'--password={shlex.quote(password)} '
f'-sN -e {shlex.quote(query)}'
)
# silent=True: we log our own message on failure and don't want the
# password-bearing command line dumped into logs on error.
success, output = BaseDispatcher.exec_command(cmd, silent=True)
if not success:
raise CMAPIBasicError(
'Failed to query information_schema.PLUGINS on local '
'MariaDB node. Ensure MariaDB is running and '
'CrossEngineSupport credentials are valid before running '
'install_es.'
)
plugins: List[Tuple[str, str]] = []
for line in output.splitlines():
parts = line.split('\t')
if len(parts) >= 2 and parts[0]:
plugins.append((parts[0].strip(), parts[1].strip()))
return plugins
@staticmethod
def check_installed_plugins(
config: str = DEFAULT_MCS_CONF_PATH,
) -> None:
"""Detect ACTIVE plugins not supported by install_es auto-upgrade.
Raises CMAPIBasicError listing every unsupported plugin along
with per-plugin manual upgrade instructions. Bundled MariaDB
engines (InnoDB, Aria, MyISAM, Columnstore, standard auth
plugins, etc.) are ignored — only plugins present in
UNSUPPORTED_PLUGINS_AUTOUPGRADE are reported.
"""
active = PreInstallManager._get_active_plugins(config)
detected: List[Tuple[str, str, str]] = []
for name, ptype in active:
instructions = UNSUPPORTED_PLUGINS_AUTOUPGRADE.get(name.upper())
if instructions is not None:
detected.append((name, ptype, instructions))
if not detected:
logging.info(
'Plugin precheck: no unsupported plugins detected.'
)
return
lines = [
'Detected MariaDB plugins that install_es cannot upgrade '
'automatically. Upgrade each of them manually, then re-run '
'install_es:'
]
for name, ptype, instructions in detected:
lines.append(f' - {name} ({ptype}): {instructions}')
message = '\n'.join(lines)
logging.error(message)
raise CMAPIBasicError(message)

View File

@@ -27,10 +27,11 @@ from cmapi_server.constants import (
from cmapi_server.controllers.api_clients import (
ClusterControllerClient, NodeControllerClient
)
from cmapi_server.exceptions import CEJError
from cmapi_server.exceptions import CEJError, CMAPIBasicError
from cmapi_server.handlers.cej import CEJPasswordHandler
from cmapi_server.helpers import get_active_nodes, get_cej_info, get_config_parser, get_current_key
from cmapi_server.managers.transaction import TransactionManager
from cmapi_server.managers.upgrade.preinstall import PreInstallManager
from cmapi_server.managers.upgrade.utils import ComparableVersion
from cmapi_server.process_dispatchers.base import BaseDispatcher
from mcs_cluster_tool.constants import MCS_COLUMNSTORE_REVIEW_SH
@@ -738,6 +739,17 @@ def install_es(
node_api_client, token, target_version, console
)
# Prechecks: fail fast, before the cluster is stopped.
console.print('Running pre-upgrade checks...', style='green')
try:
PreInstallManager.check_gtid_strict_mode()
PreInstallManager.check_installed_plugins()
except CMAPIBasicError as exc:
console.print('[red]Pre-upgrade check failed:[/red]')
console.print(exc.message)
raise typer.Exit(code=1)
console.print('[green]Pre-upgrade checks passed ✓[/green]')
# Retrieve current versions (handles mismatch display)
versions = get_current_versions(cluster_api_client, console, ignore_mismatch)
mdb_curr_ver = versions['server_version']