Skip to content

Commit

Permalink
el9to10: actors: mysql: Split into scanner and checker actors
Browse files Browse the repository at this point in the history
  • Loading branch information
SlouchyButton committed Jan 23, 2025
1 parent 9aebba4 commit 83e4219
Show file tree
Hide file tree
Showing 11 changed files with 264 additions and 70 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from leapp.actors import Actor
from leapp.libraries.actor.mysqlcheck import report_installed_packages
from leapp.models import DistributionSignedRPM, Report
from leapp.libraries.actor import mysqlcheck
from leapp.models import MySQLConfiguration, Report
from leapp.tags import ChecksPhaseTag, IPUWorkflowTag


Expand All @@ -12,9 +12,9 @@ class MySQLCheck(Actor):
with MySQL installed.
"""
name = 'mysql_check'
consumes = (DistributionSignedRPM,)
consumes = (MySQLConfiguration,)
produces = (Report,)
tags = (ChecksPhaseTag, IPUWorkflowTag)

def process(self):
report_installed_packages()
def process(self) -> None:
mysqlcheck.process()
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from leapp import reporting
from leapp.libraries.common.rpms import has_package
from leapp.libraries.stdlib import api
from leapp.models import DistributionSignedRPM
from leapp.models import MySQLConfiguration
from leapp.exceptions import StopActorExecutionError

import subprocess

Expand Down Expand Up @@ -31,7 +31,7 @@
report_server_inst_link_url = 'https://access.redhat.com/articles/7099234'


def _generate_mysql_present_report():
def _generate_mysql_present_report() -> None:
"""
Create report on mysql-server package installation detection.
Expand Down Expand Up @@ -66,7 +66,7 @@ def _generate_mysql_present_report():
])


def _generate_deprecated_config_report(found_options, found_arguments):
def _generate_deprecated_config_report(found_options, found_arguments) -> None:
"""
Create report on mysql-server deprecated configuration.
Expand Down Expand Up @@ -134,7 +134,7 @@ def _generate_deprecated_config_report(found_options, found_arguments):
])


def _generate_report(found_options, found_arguments):
def _generate_report(found_options, found_arguments) -> None:
"""
Create report on mysql-server package installation detection.
Expand All @@ -149,64 +149,14 @@ def _generate_report(found_options, found_arguments):
_generate_mysql_present_report()


def _check_incompatible_config():
"""
Get incompatible configuration options. Since MySQL can have basically
unlimited number of config files that can link to one another, most
convenient way is running `mysqld` command with `--validate-config
--log-error-verbosity=2` arguments. Validate config only validates the
config, without starting the MySQL server. Verbosity=2 is required to show
deprecated options - which are removed after upgrade.
Example output:
2024-12-18T11:40:04.725073Z 0 [Warning] [MY-011069] [Server]
The syntax '--old' is deprecated and will be removed in a future release.
"""
# mysqld --validate-config --log-error-verbosity=2
# 2024-12-18T11:40:04.725073Z 0 [Warning] [MY-011069] [Server]
# The syntax '--old' is deprecated and will be removed in a future release.

found_options = set()
out = subprocess.run(['mysqld', '--validate-config', '--log-error-verbosity=2'],
capture_output=True,
check=False)

stderr = out.stderr.decode("utf-8")
if 'deprecated' in stderr:
found_options = {arg for arg
in REMOVED_ARGS
if arg in stderr}
return found_options


def _check_incompatible_launch_param():
"""
Get incompatible launch parameters from systemd service override file
located at /etc/systemd/system/mysqld.service.d/override.conf
"""

found_arguments = set()
try:
with open('/etc/systemd/system/mysqld.service.d/override.conf') as f:
file_content = f.read()
found_arguments = {arg for arg
in REMOVED_ARGS
if arg in file_content}
except OSError:
# File probably doesn't exist, ignore it and pass
pass
def process() -> None:
msg = next(api.consume(MySQLConfiguration), None)
if not msg:
raise StopActorExecutionError('Expected MySQLConfiguration, but got None')

return found_arguments


def report_installed_packages(_context=api):
"""
Create reports according to detected MySQL packages.
Create the report if the mysql-server rpm (RH signed) is installed.
"""

if has_package(DistributionSignedRPM, 'mysql-server', context=_context):
found_options = _check_incompatible_config()
found_arguments = _check_incompatible_launch_param()
_generate_report(found_options, found_arguments)
if msg.mysql_present:
_generate_report(msg.removed_options, msg.removed_arguments)
else:
api.current_logger().debug(
'mysql-server package not found, no report generated'
)
20 changes: 20 additions & 0 deletions repos/system_upgrade/el9toel10/actors/mysql/scanmysql/actor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from leapp.actors import Actor
from leapp.libraries.actor import scanmysql
from leapp.models import DistributionSignedRPM, MySQLConfiguration
from leapp.tags import FactsPhaseTag, IPUWorkflowTag


class ScanMySQL(Actor):
"""
Actor checking for presence of MySQL installation.
Provides user with information related to upgrading systems
with MySQL installed.
"""
name = 'scan_mysql'
consumes = (DistributionSignedRPM,)
produces = (MySQLConfiguration,)
tags = (FactsPhaseTag, IPUWorkflowTag)

def process(self) -> None:
self.produce(scanmysql.check_status())
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
from leapp.models import DistributionSignedRPM, MySQLConfiguration
from leapp.libraries.common.rpms import has_package
from leapp.libraries.stdlib import api

import subprocess

# https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html
# https://dev.mysql.com/doc/refman/8.0/en/server-options.html
# https://dev.mysql.com/doc/refman/8.4/en/mysql-nutshell.html
REMOVED_ARGS = [
'--avoid-temporal-upgrade',
'avoid_temporal_upgrade',
'--show-old-temporals',
'show_old_temporals',
'--old',
'--new',
'--default-authentication-plugin',
'default_authentication_plugin',
'--no-dd-upgrade',
'--language',
'--ssl',
'--admin-ssl',
'--character-set-client-handshake',
'--old-style-user-limits',
]


def _check_incompatible_config() -> set[str]:
"""
Get incompatible configuration options. Since MySQL can have basically
unlimited number of config files that can link to one another, most
convenient way is running `mysqld` command with `--validate-config
--log-error-verbosity=2` arguments. Validate config only validates the
config, without starting the MySQL server. Verbosity=2 is required to show
deprecated options - which are removed after upgrade.
Example output:
2024-12-18T11:40:04.725073Z 0 [Warning] [MY-011069] [Server]
The syntax '--old' is deprecated and will be removed in a future release.
Returns:
set[str]: Config options found that will be removed
"""

found_options = set()
out = subprocess.run(['mysqld', '--validate-config', '--log-error-verbosity=2'],
capture_output=True,
check=False)

stderr = out.stderr.decode("utf-8")
if 'deprecated' in stderr:
found_options = {arg for arg
in REMOVED_ARGS
if arg in stderr}
return found_options


def _check_incompatible_launch_param() -> set[str]:
"""
Get incompatible launch parameters from systemd service override file
located at /etc/systemd/system/mysqld.service.d/override.conf
Returns:
set[str]: Launch parameters found that will be removed
"""

found_arguments = set()
try:
with open('/etc/systemd/system/mysqld.service.d/override.conf') as f:
file_content = f.read()
found_arguments = {arg for arg
in REMOVED_ARGS
if arg in file_content}
except OSError:
# File probably doesn't exist, ignore it and pass
pass

return found_arguments


def check_status(_context=api) -> MySQLConfiguration:
"""
Check whether MySQL is installed and if so whether config is compatible with
newer version.
Returns:
MySQLConfiguration: Current status of MySQL on the system
"""

mysql_present = has_package(DistributionSignedRPM, 'mysql-server', context=_context)

found_options = None
found_arguments = None
if mysql_present:
found_options = list(_check_incompatible_config())
found_arguments = list(_check_incompatible_launch_param())

return MySQLConfiguration(mysql_present=mysql_present,
removed_options=found_options,
removed_arguments=found_arguments)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#
# This group are read by MySQL server.
# Use it for options that only the server (but not clients) should see
#
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/en/server-configuration-defaults.html

# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mysqld according to the
# instructions in http://fedoraproject.org/wiki/Systemd

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysql/mysqld.log
pid-file=/run/mysqld/mysqld.pid
old=true
avoid_temporal_upgrade=true
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#
# This group are read by MySQL server.
# Use it for options that only the server (but not clients) should see
#
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/en/server-configuration-defaults.html

# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mysqld according to the
# instructions in http://fedoraproject.org/wiki/Systemd

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysql/mysqld.log
pid-file=/run/mysqld/mysqld.pid
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[Service]
ExecStart=
ExecStart=/usr/libexec/mysqld --language=/usr/local/mysql/share/mysql/english/ --basedir=/usr
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
2025-01-23T15:28:05.352420Z 0 [Warning] [MY-011069] [Server] The syntax '--old' is deprecated and will be removed in a future release.
2025-01-23T15:28:05.352425Z 0 [Warning] [MY-011069] [Server] The syntax 'avoid_temporal_upgrade' is deprecated and will be removed in a future release.
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import pytest

from leapp import reporting
from leapp.libraries.actor.mysqlcheck import report_installed_packages
from leapp.libraries.common.testutils import create_report_mocked, CurrentActorMocked
from leapp.libraries.stdlib import api
from leapp.models import DistributionSignedRPM, RPM


def _generate_rpm_with_name(name):
"""
Generate new RPM model item with given name.
Parameters:
name (str): rpm name
Returns:
rpm (RPM): new RPM object with name parameter set
"""
return RPM(name=name,
version='0.1',
release='1.sm01',
epoch='1',
pgpsig='RSA/SHA256, Mon 01 Jan 1970 00:00:00 AM -03, Key ID 199e2f91fd431d51',
packager='Red Hat, Inc. <http://bugzilla.redhat.com/bugzilla>',
arch='noarch')


@pytest.mark.parametrize('has_server', [
(True), # with server
(False), # without server
])
def test_actor_execution(monkeypatch, has_server):
"""
Parametrized helper function for test_actor_* functions.
First generate list of RPM models based on set arguments. Then, run
the actor fed with our RPM list. Finally, assert Reports
according to set arguments.
Parameters:
has_server (bool): mysql-server installed
"""

# Couple of random packages
rpms = [_generate_rpm_with_name('sed'),
_generate_rpm_with_name('htop')]

if has_server:
# Add mysql-server
rpms += [_generate_rpm_with_name('mysql-server')]

curr_actor_mocked = CurrentActorMocked(msgs=[DistributionSignedRPM(items=rpms)])
monkeypatch.setattr(api, 'current_actor', curr_actor_mocked)
monkeypatch.setattr(reporting, "create_report", create_report_mocked())

# Executed actor fed with fake RPMs
report_installed_packages(_context=api)

if has_server:
# Assert for mysql-server package installed
assert reporting.create_report.called == 1
else:
# Assert for no mysql packages installed
assert not reporting.create_report.called
18 changes: 18 additions & 0 deletions repos/system_upgrade/el9toel10/models/mysql.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from leapp.models import fields, Model
from leapp.topics import SystemInfoTopic


class MySQLConfiguration(Model):
"""
Model describing current state of MySQL server including configuration compatibility
"""

topic = SystemInfoTopic

mysql_present = fields.Boolean(default=False)

"""
Configured options which are removed in RHEL 10 MySQL
"""
removed_options = fields.List(fields.String(), default=[])
removed_arguments = fields.List(fields.String(), default=[])

0 comments on commit 83e4219

Please sign in to comment.