Skip to content

Commit 83e4219

Browse files
committed
el9to10: actors: mysql: Split into scanner and checker actors
1 parent 9aebba4 commit 83e4219

File tree

11 files changed

+264
-70
lines changed

11 files changed

+264
-70
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from leapp.actors import Actor
2-
from leapp.libraries.actor.mysqlcheck import report_installed_packages
3-
from leapp.models import DistributionSignedRPM, Report
2+
from leapp.libraries.actor import mysqlcheck
3+
from leapp.models import MySQLConfiguration, Report
44
from leapp.tags import ChecksPhaseTag, IPUWorkflowTag
55

66

@@ -12,9 +12,9 @@ class MySQLCheck(Actor):
1212
with MySQL installed.
1313
"""
1414
name = 'mysql_check'
15-
consumes = (DistributionSignedRPM,)
15+
consumes = (MySQLConfiguration,)
1616
produces = (Report,)
1717
tags = (ChecksPhaseTag, IPUWorkflowTag)
1818

19-
def process(self):
20-
report_installed_packages()
19+
def process(self) -> None:
20+
mysqlcheck.process()

repos/system_upgrade/el9toel10/actors/mysqlcheck/libraries/mysqlcheck.py renamed to repos/system_upgrade/el9toel10/actors/mysql/checkmysql/libraries/mysqlcheck.py

Lines changed: 15 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from leapp import reporting
2-
from leapp.libraries.common.rpms import has_package
32
from leapp.libraries.stdlib import api
4-
from leapp.models import DistributionSignedRPM
3+
from leapp.models import MySQLConfiguration
4+
from leapp.exceptions import StopActorExecutionError
55

66
import subprocess
77

@@ -31,7 +31,7 @@
3131
report_server_inst_link_url = 'https://access.redhat.com/articles/7099234'
3232

3333

34-
def _generate_mysql_present_report():
34+
def _generate_mysql_present_report() -> None:
3535
"""
3636
Create report on mysql-server package installation detection.
3737
@@ -66,7 +66,7 @@ def _generate_mysql_present_report():
6666
])
6767

6868

69-
def _generate_deprecated_config_report(found_options, found_arguments):
69+
def _generate_deprecated_config_report(found_options, found_arguments) -> None:
7070
"""
7171
Create report on mysql-server deprecated configuration.
7272
@@ -134,7 +134,7 @@ def _generate_deprecated_config_report(found_options, found_arguments):
134134
])
135135

136136

137-
def _generate_report(found_options, found_arguments):
137+
def _generate_report(found_options, found_arguments) -> None:
138138
"""
139139
Create report on mysql-server package installation detection.
140140
@@ -149,64 +149,14 @@ def _generate_report(found_options, found_arguments):
149149
_generate_mysql_present_report()
150150

151151

152-
def _check_incompatible_config():
153-
"""
154-
Get incompatible configuration options. Since MySQL can have basically
155-
unlimited number of config files that can link to one another, most
156-
convenient way is running `mysqld` command with `--validate-config
157-
--log-error-verbosity=2` arguments. Validate config only validates the
158-
config, without starting the MySQL server. Verbosity=2 is required to show
159-
deprecated options - which are removed after upgrade.
160-
161-
Example output:
162-
2024-12-18T11:40:04.725073Z 0 [Warning] [MY-011069] [Server]
163-
The syntax '--old' is deprecated and will be removed in a future release.
164-
"""
165-
# mysqld --validate-config --log-error-verbosity=2
166-
# 2024-12-18T11:40:04.725073Z 0 [Warning] [MY-011069] [Server]
167-
# The syntax '--old' is deprecated and will be removed in a future release.
168-
169-
found_options = set()
170-
out = subprocess.run(['mysqld', '--validate-config', '--log-error-verbosity=2'],
171-
capture_output=True,
172-
check=False)
173-
174-
stderr = out.stderr.decode("utf-8")
175-
if 'deprecated' in stderr:
176-
found_options = {arg for arg
177-
in REMOVED_ARGS
178-
if arg in stderr}
179-
return found_options
180-
181-
182-
def _check_incompatible_launch_param():
183-
"""
184-
Get incompatible launch parameters from systemd service override file
185-
located at /etc/systemd/system/mysqld.service.d/override.conf
186-
"""
187-
188-
found_arguments = set()
189-
try:
190-
with open('/etc/systemd/system/mysqld.service.d/override.conf') as f:
191-
file_content = f.read()
192-
found_arguments = {arg for arg
193-
in REMOVED_ARGS
194-
if arg in file_content}
195-
except OSError:
196-
# File probably doesn't exist, ignore it and pass
197-
pass
152+
def process() -> None:
153+
msg = next(api.consume(MySQLConfiguration), None)
154+
if not msg:
155+
raise StopActorExecutionError('Expected MySQLConfiguration, but got None')
198156

199-
return found_arguments
200-
201-
202-
def report_installed_packages(_context=api):
203-
"""
204-
Create reports according to detected MySQL packages.
205-
206-
Create the report if the mysql-server rpm (RH signed) is installed.
207-
"""
208-
209-
if has_package(DistributionSignedRPM, 'mysql-server', context=_context):
210-
found_options = _check_incompatible_config()
211-
found_arguments = _check_incompatible_launch_param()
212-
_generate_report(found_options, found_arguments)
157+
if msg.mysql_present:
158+
_generate_report(msg.removed_options, msg.removed_arguments)
159+
else:
160+
api.current_logger().debug(
161+
'mysql-server package not found, no report generated'
162+
)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from leapp.actors import Actor
2+
from leapp.libraries.actor import scanmysql
3+
from leapp.models import DistributionSignedRPM, MySQLConfiguration
4+
from leapp.tags import FactsPhaseTag, IPUWorkflowTag
5+
6+
7+
class ScanMySQL(Actor):
8+
"""
9+
Actor checking for presence of MySQL installation.
10+
11+
Provides user with information related to upgrading systems
12+
with MySQL installed.
13+
"""
14+
name = 'scan_mysql'
15+
consumes = (DistributionSignedRPM,)
16+
produces = (MySQLConfiguration,)
17+
tags = (FactsPhaseTag, IPUWorkflowTag)
18+
19+
def process(self) -> None:
20+
self.produce(scanmysql.check_status())
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
from leapp.models import DistributionSignedRPM, MySQLConfiguration
2+
from leapp.libraries.common.rpms import has_package
3+
from leapp.libraries.stdlib import api
4+
5+
import subprocess
6+
7+
# https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html
8+
# https://dev.mysql.com/doc/refman/8.0/en/server-options.html
9+
# https://dev.mysql.com/doc/refman/8.4/en/mysql-nutshell.html
10+
REMOVED_ARGS = [
11+
'--avoid-temporal-upgrade',
12+
'avoid_temporal_upgrade',
13+
'--show-old-temporals',
14+
'show_old_temporals',
15+
'--old',
16+
'--new',
17+
'--default-authentication-plugin',
18+
'default_authentication_plugin',
19+
'--no-dd-upgrade',
20+
'--language',
21+
'--ssl',
22+
'--admin-ssl',
23+
'--character-set-client-handshake',
24+
'--old-style-user-limits',
25+
]
26+
27+
28+
def _check_incompatible_config() -> set[str]:
29+
"""
30+
Get incompatible configuration options. Since MySQL can have basically
31+
unlimited number of config files that can link to one another, most
32+
convenient way is running `mysqld` command with `--validate-config
33+
--log-error-verbosity=2` arguments. Validate config only validates the
34+
config, without starting the MySQL server. Verbosity=2 is required to show
35+
deprecated options - which are removed after upgrade.
36+
37+
Example output:
38+
2024-12-18T11:40:04.725073Z 0 [Warning] [MY-011069] [Server]
39+
The syntax '--old' is deprecated and will be removed in a future release.
40+
41+
Returns:
42+
set[str]: Config options found that will be removed
43+
"""
44+
45+
found_options = set()
46+
out = subprocess.run(['mysqld', '--validate-config', '--log-error-verbosity=2'],
47+
capture_output=True,
48+
check=False)
49+
50+
stderr = out.stderr.decode("utf-8")
51+
if 'deprecated' in stderr:
52+
found_options = {arg for arg
53+
in REMOVED_ARGS
54+
if arg in stderr}
55+
return found_options
56+
57+
58+
def _check_incompatible_launch_param() -> set[str]:
59+
"""
60+
Get incompatible launch parameters from systemd service override file
61+
located at /etc/systemd/system/mysqld.service.d/override.conf
62+
63+
Returns:
64+
set[str]: Launch parameters found that will be removed
65+
"""
66+
67+
found_arguments = set()
68+
try:
69+
with open('/etc/systemd/system/mysqld.service.d/override.conf') as f:
70+
file_content = f.read()
71+
found_arguments = {arg for arg
72+
in REMOVED_ARGS
73+
if arg in file_content}
74+
except OSError:
75+
# File probably doesn't exist, ignore it and pass
76+
pass
77+
78+
return found_arguments
79+
80+
81+
def check_status(_context=api) -> MySQLConfiguration:
82+
"""
83+
Check whether MySQL is installed and if so whether config is compatible with
84+
newer version.
85+
86+
Returns:
87+
MySQLConfiguration: Current status of MySQL on the system
88+
"""
89+
90+
mysql_present = has_package(DistributionSignedRPM, 'mysql-server', context=_context)
91+
92+
found_options = None
93+
found_arguments = None
94+
if mysql_present:
95+
found_options = list(_check_incompatible_config())
96+
found_arguments = list(_check_incompatible_launch_param())
97+
98+
return MySQLConfiguration(mysql_present=mysql_present,
99+
removed_options=found_options,
100+
removed_arguments=found_arguments)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#
2+
# This group are read by MySQL server.
3+
# Use it for options that only the server (but not clients) should see
4+
#
5+
# For advice on how to change settings please see
6+
# http://dev.mysql.com/doc/refman/en/server-configuration-defaults.html
7+
8+
# Settings user and group are ignored when systemd is used.
9+
# If you need to run mysqld under a different user or group,
10+
# customize your systemd unit file for mysqld according to the
11+
# instructions in http://fedoraproject.org/wiki/Systemd
12+
13+
[mysqld]
14+
datadir=/var/lib/mysql
15+
socket=/var/lib/mysql/mysql.sock
16+
log-error=/var/log/mysql/mysqld.log
17+
pid-file=/run/mysqld/mysqld.pid
18+
old=true
19+
avoid_temporal_upgrade=true
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#
2+
# This group are read by MySQL server.
3+
# Use it for options that only the server (but not clients) should see
4+
#
5+
# For advice on how to change settings please see
6+
# http://dev.mysql.com/doc/refman/en/server-configuration-defaults.html
7+
8+
# Settings user and group are ignored when systemd is used.
9+
# If you need to run mysqld under a different user or group,
10+
# customize your systemd unit file for mysqld according to the
11+
# instructions in http://fedoraproject.org/wiki/Systemd
12+
13+
[mysqld]
14+
datadir=/var/lib/mysql
15+
socket=/var/lib/mysql/mysql.sock
16+
log-error=/var/log/mysql/mysqld.log
17+
pid-file=/run/mysqld/mysqld.pid
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[Service]
2+
ExecStart=
3+
ExecStart=/usr/libexec/mysqld --language=/usr/local/mysql/share/mysql/english/ --basedir=/usr
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2025-01-23T15:28:05.352420Z 0 [Warning] [MY-011069] [Server] The syntax '--old' is deprecated and will be removed in a future release.
2+
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.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import pytest
2+
3+
from leapp import reporting
4+
from leapp.libraries.actor.mysqlcheck import report_installed_packages
5+
from leapp.libraries.common.testutils import create_report_mocked, CurrentActorMocked
6+
from leapp.libraries.stdlib import api
7+
from leapp.models import DistributionSignedRPM, RPM
8+
9+
10+
def _generate_rpm_with_name(name):
11+
"""
12+
Generate new RPM model item with given name.
13+
14+
Parameters:
15+
name (str): rpm name
16+
17+
Returns:
18+
rpm (RPM): new RPM object with name parameter set
19+
"""
20+
return RPM(name=name,
21+
version='0.1',
22+
release='1.sm01',
23+
epoch='1',
24+
pgpsig='RSA/SHA256, Mon 01 Jan 1970 00:00:00 AM -03, Key ID 199e2f91fd431d51',
25+
packager='Red Hat, Inc. <http://bugzilla.redhat.com/bugzilla>',
26+
arch='noarch')
27+
28+
29+
@pytest.mark.parametrize('has_server', [
30+
(True), # with server
31+
(False), # without server
32+
])
33+
def test_actor_execution(monkeypatch, has_server):
34+
"""
35+
Parametrized helper function for test_actor_* functions.
36+
37+
First generate list of RPM models based on set arguments. Then, run
38+
the actor fed with our RPM list. Finally, assert Reports
39+
according to set arguments.
40+
41+
Parameters:
42+
has_server (bool): mysql-server installed
43+
"""
44+
45+
# Couple of random packages
46+
rpms = [_generate_rpm_with_name('sed'),
47+
_generate_rpm_with_name('htop')]
48+
49+
if has_server:
50+
# Add mysql-server
51+
rpms += [_generate_rpm_with_name('mysql-server')]
52+
53+
curr_actor_mocked = CurrentActorMocked(msgs=[DistributionSignedRPM(items=rpms)])
54+
monkeypatch.setattr(api, 'current_actor', curr_actor_mocked)
55+
monkeypatch.setattr(reporting, "create_report", create_report_mocked())
56+
57+
# Executed actor fed with fake RPMs
58+
report_installed_packages(_context=api)
59+
60+
if has_server:
61+
# Assert for mysql-server package installed
62+
assert reporting.create_report.called == 1
63+
else:
64+
# Assert for no mysql packages installed
65+
assert not reporting.create_report.called
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from leapp.models import fields, Model
2+
from leapp.topics import SystemInfoTopic
3+
4+
5+
class MySQLConfiguration(Model):
6+
"""
7+
Model describing current state of MySQL server including configuration compatibility
8+
"""
9+
10+
topic = SystemInfoTopic
11+
12+
mysql_present = fields.Boolean(default=False)
13+
14+
"""
15+
Configured options which are removed in RHEL 10 MySQL
16+
"""
17+
removed_options = fields.List(fields.String(), default=[])
18+
removed_arguments = fields.List(fields.String(), default=[])

0 commit comments

Comments
 (0)