Skip to content

Commit

Permalink
Move generic entities into system_upgrades/common repo
Browse files Browse the repository at this point in the history
In order to prepare for adding the el8_to_el9 upgrade path repository,
we want to move any generic actors, models and libraries into the
system_upgrades/common repo so it can be used by other repositories.
  • Loading branch information
pirat89 committed Jun 25, 2021
1 parent 53c3ba0 commit 0eca81c
Show file tree
Hide file tree
Showing 362 changed files with 211 additions and 291 deletions.
1 change: 1 addition & 0 deletions repos/system_upgrade/common/.leapp/info
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"name": "system_upgrade_common", "id": "644900a5-c347-43a3-bfab-f448f46d9647", "repos": ["efcf9016-f2d1-4609-9329-a298e6587b3c"]}
6 changes: 6 additions & 0 deletions repos/system_upgrade/common/.leapp/leapp.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

[repositories]
repo_path=${repository:root_dir}

[database]
path=${repository:state_dir}/leapp.db
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

class Biosdevname(Actor):
"""
Enable biosdevname on RHEL8 if all interfaces on RHEL7 use biosdevname naming scheme and if machine vendor is DELL
Enable biosdevname on the target RHEL system if all interfaces on the source RHEL
system use biosdevname naming scheme and if machine vendor is DELL
"""

name = 'biosdevname'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ def all_interfaces_biosdevname(interfaces):


def enable_biosdevname():
api.current_logger().info("Biosdevname naming scheme in use, explicitely enabling biosdevname on RHEL-8")
api.current_logger().info(
"Biosdevname naming scheme in use, explicitely enabling biosdevname on the target RHEL system"
)
api.produce(KernelCmdlineArg(**{'key': 'biosdevname', 'value': '1'}))


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ def test_enable_biosdevname(monkeypatch):

biosdevname.enable_biosdevname()
assert (
"Biosdevname naming scheme in use, explicitely enabling biosdevname on RHEL-8"
in api.current_logger.infomsg
"Biosdevname naming scheme in use, explicitely enabling biosdevname on the target RHEL system"
in api.current_logger.infomsg
)
assert result[0].key == "biosdevname"
assert result[0].value == "1"
Expand Down
30 changes: 30 additions & 0 deletions repos/system_upgrade/common/actors/enablerhsmtargetrepos/actor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from leapp.actors import Actor
from leapp.libraries.actor import enablerhsmtargetrepos
from leapp.models import UsedTargetRepositories
from leapp.tags import FirstBootPhaseTag, IPUWorkflowTag


class EnableRHSMTargetRepos(Actor):
"""
On the upgraded target system, set release and enable repositories that were used during the upgrade
transaction.
We are enabling those RHEL target repos that are equivalent to the enabled source RHEL ones available.
The BaseOS and AppStream repos are enabled on the target RHEL by default. Any other repository needs to
be enabled specifically using the subscription-manager (RHSM) utility. In case some custom repo was used
during the upgrade transaction, this won't be enabled by this actors as it is unknown to the subscription-manager.
We need to overwrite any RHSM release that may have been set before the upgrade, e.g. 7.6. Reasons:
- If we leave the old source RHEL release set, dnf calls on the upgraded target RHEL would fail.
- If we merely unset the release, users might end up updating the system to a newer version than the upgrade
was supposed to be upgrading to.
"""

name = 'enable_rhsm_target_repos'
consumes = (UsedTargetRepositories,)
produces = ()
tags = (IPUWorkflowTag, FirstBootPhaseTag)

def process(self):
enablerhsmtargetrepos.set_rhsm_release()
enablerhsmtargetrepos.enable_rhsm_repos()
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


def set_rhsm_release():
"""Set the RHSM release to the target RHEL 8 minor version."""
"""Set the RHSM release to the target RHEL minor version."""
if rhsm.skip_rhsm():
api.current_logger().debug('Skipping setting the RHSM release due to --no-rhsm or environment variables.')
return
Expand All @@ -17,13 +17,13 @@ def set_rhsm_release():
rhsm.set_release(mounting.NotIsolatedActions(base_dir='/'), target_version)
except CalledProcessError as err:
api.current_logger().warning('Unable to set the {0} release through subscription-manager. When using dnf,'
' content of the latest RHEL 8 minor version will be downloaded.\n{1}'
.format(target_version, str(err)))
' content of the latest RHEL {1} minor version will be downloaded.\n{2}'
.format(target_version, target_version.split('.')[0], str(err)))


def enable_rhsm_repos():
"""
Try enabling all the RHEL 8 repositories that have been used for the upgrade transaction.
Try enabling all the target RHEL repositories that have been used for the upgrade transaction.
In case of custom repositories, the subscription-manager reports an error that it doesn't know them, but it enables
the known repositories.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import pytest

from leapp.exceptions import StopActorExecutionError
from leapp.libraries.actor import enablerhsmreposonrhel8
from leapp.libraries.actor import enablerhsmtargetrepos
from leapp.libraries.common import config, mounting, rhsm
from leapp.libraries.common.testutils import CurrentActorMocked, logger_mocked
from leapp.libraries.stdlib import CalledProcessError, api
Expand Down Expand Up @@ -51,7 +51,7 @@ def test_setrelease(monkeypatch):
monkeypatch.setattr(mounting, 'NotIsolatedActions', klass)
monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(dst_ver='8.0'))
monkeypatch.setattr(config, 'get_product_type', lambda dummy: 'ga')
enablerhsmreposonrhel8.set_rhsm_release()
enablerhsmtargetrepos.set_rhsm_release()
assert commands_called and len(commands_called) == 1
assert commands_called[0][0][-1] == '8.0'

Expand All @@ -68,7 +68,7 @@ def test_setrelease_submgr_throwing_error(monkeypatch):
else:
monkeypatch.setattr(rhsm, 'set_release', rhsm.set_release.__wrapped__.__wrapped__)
with pytest.raises(StopActorExecutionError):
enablerhsmreposonrhel8.set_rhsm_release()
enablerhsmtargetrepos.set_rhsm_release()


@pytest.mark.parametrize('product', ['beta', 'htb'])
Expand All @@ -79,7 +79,7 @@ def test_setrelease_skip_rhsm(monkeypatch, product):
monkeypatch.setattr(config, 'get_product_type', lambda dummy: product)
# To make this work we need to re-apply the decorator, so it respects the environment variable
monkeypatch.setattr(rhsm, 'set_release', rhsm.with_rhsm(rhsm.set_release))
enablerhsmreposonrhel8.set_rhsm_release()
enablerhsmtargetrepos.set_rhsm_release()
assert not commands_called


Expand All @@ -91,37 +91,37 @@ def construct_UTRepo_consume(repoids):
def test_get_unique_repoids(monkeypatch):
repoids = (['some-repo', 'some-repo', 'another-repo'])
monkeypatch.setattr(api, 'consume', construct_UTRepo_consume(repoids))
assert enablerhsmreposonrhel8.get_repos_to_enable() == {'some-repo', 'another-repo'}
assert enablerhsmtargetrepos.get_repos_to_enable() == {'some-repo', 'another-repo'}


def test_get_submgr_cmd():
assert enablerhsmreposonrhel8.get_submgr_cmd({'some-repo'}) == ['subscription-manager', 'repos', '--enable',
'some-repo']
assert enablerhsmtargetrepos.get_submgr_cmd({'some-repo'}) == ['subscription-manager', 'repos', '--enable',
'some-repo']


def test_running_submgr_ok(monkeypatch):
monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(dst_ver='8.0', envars={'LEAPP_NO_RHSM': '0'}), )
monkeypatch.setattr(enablerhsmreposonrhel8, 'get_repos_to_enable', lambda: {'some-repo'})
monkeypatch.setattr(enablerhsmreposonrhel8, 'run', run_mocked())
enablerhsmreposonrhel8.enable_rhsm_repos()
assert enablerhsmreposonrhel8.run.called
assert 'subscription-manager' in enablerhsmreposonrhel8.run.args[0][0]
monkeypatch.setattr(enablerhsmtargetrepos, 'get_repos_to_enable', lambda: {'some-repo'})
monkeypatch.setattr(enablerhsmtargetrepos, 'run', run_mocked())
enablerhsmtargetrepos.enable_rhsm_repos()
assert enablerhsmtargetrepos.run.called
assert 'subscription-manager' in enablerhsmtargetrepos.run.args[0][0]


def test_running_submgr_fail(monkeypatch):
monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(dst_ver='8.0', envars={'LEAPP_NO_RHSM': '0'}), )
monkeypatch.setattr(enablerhsmreposonrhel8, 'get_repos_to_enable', lambda: {'some-repo'})
monkeypatch.setattr(enablerhsmreposonrhel8, 'run', run_mocked(raise_err=True))
monkeypatch.setattr(enablerhsmtargetrepos, 'get_repos_to_enable', lambda: {'some-repo'})
monkeypatch.setattr(enablerhsmtargetrepos, 'run', run_mocked(raise_err=True))
monkeypatch.setattr(api, 'current_logger', logger_mocked())
enablerhsmreposonrhel8.enable_rhsm_repos()
assert enablerhsmreposonrhel8.run.called
enablerhsmtargetrepos.enable_rhsm_repos()
assert enablerhsmtargetrepos.run.called
assert api.current_logger.warnmsg


def test_enable_repos_skip_rhsm(monkeypatch):
monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(envars={'LEAPP_NO_RHSM': '1'}))
monkeypatch.setattr(enablerhsmreposonrhel8, 'run', run_mocked())
monkeypatch.setattr(enablerhsmtargetrepos, 'run', run_mocked())
monkeypatch.setattr(api, 'current_logger', logger_mocked())
enablerhsmreposonrhel8.enable_rhsm_repos()
assert not enablerhsmreposonrhel8.run.called
enablerhsmtargetrepos.enable_rhsm_repos()
assert not enablerhsmtargetrepos.run.called
assert api.current_logger.dbgmsg
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ def process(self):
leapp_env_vars=ipuworkflowconfig.get_env_vars(),
os_release=os_release,
architecture=platform.machine(),
version=Version(source=os_release.version_id, target=target_version),
version=Version(
source=os_release.version_id,
target=target_version
),
kernel=ipuworkflowconfig.get_booted_kernel(),
flavour=flavour
))
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
from leapp.libraries.stdlib import run, CalledProcessError
from leapp.models import EnvVar, OSRelease

CURRENT_TARGET_VERSION = '8.4'
CURRENT_SAP_HANA_TARGET_VERSION = '8.2'

ENV_IGNORE = ('LEAPP_CURRENT_PHASE', 'LEAPP_CURRENT_ACTOR', 'LEAPP_VERBOSE',
'LEAPP_DEBUG')
Expand All @@ -19,6 +17,30 @@
HANA_BASE_PATH = '/hana/shared'
HANA_SAPCONTROL_PATH = 'exe/linuxx86_64/hdb/sapcontrol'

# map of expected upgrade paths per source system and flavour, expected
# does not mean supported. Supported paths are checked later.
upgrade_paths_map = {

# expected upgrade paths for RHEL 7
('7.6', LEAPP_UPGRADE_FLAVOUR_DEFAULT): '8.4',
('7.9', LEAPP_UPGRADE_FLAVOUR_DEFAULT): '8.4',
('7.7', LEAPP_UPGRADE_FLAVOUR_SAP_HANA): '8.2',

# expected upgrade paths for RHEL 8
('8.6', LEAPP_UPGRADE_FLAVOUR_DEFAULT): '9.0',

# unsupported fallback paths for RHEL 7
('7', LEAPP_UPGRADE_FLAVOUR_DEFAULT): '8.4',
('7', LEAPP_UPGRADE_FLAVOUR_SAP_HANA): '8.4',

# unsupported fallback paths for RHEL 8
('8', LEAPP_UPGRADE_FLAVOUR_DEFAULT): '9.0',
}


def _get_major_version(version):
return version.split('.')[0]


def get_env_vars():
"""
Expand Down Expand Up @@ -58,7 +80,9 @@ def get_os_release(path):


def get_booted_kernel():
"""Get version and release of the currently used kernel in one string."""
"""
Get version and release of the currently used kernel in one string.
"""
try:
return run(['/usr/bin/uname', '-r'])['stdout'].strip()
except CalledProcessError as e:
Expand All @@ -70,18 +94,27 @@ def get_booted_kernel():

def get_target_version(flavour=LEAPP_UPGRADE_FLAVOUR_DEFAULT):
"""
Returns the target version for the given `flavour` of upgrade. The default value for `flavour` is `default`.
Return the target version for the given `flavour` of upgrade. The default value for `flavour` is `default`.
In case the environment variable `LEAPP_DEVEL_TARGET_RELEASE` is set, the value of it will be returned.
"""
current_target_version = CURRENT_TARGET_VERSION
if flavour == LEAPP_UPGRADE_FLAVOUR_SAP_HANA:
current_target_version = CURRENT_SAP_HANA_TARGET_VERSION
return os.getenv('LEAPP_DEVEL_TARGET_RELEASE', None) or current_target_version

current_version_id = get_os_release('/etc/os-release').version_id
target_version = upgrade_paths_map.get((current_version_id, flavour), None)
if not target_version:
# If we cannot find a particular major.minor version in the map,
# we fallback to pick a target version just based on a major version.
# This can happen for example when testing not yet released versions
major_version = _get_major_version(current_version_id)
target_version = upgrade_paths_map.get((major_version, flavour), None)

return os.getenv('LEAPP_DEVEL_TARGET_RELEASE', None) or target_version


def detect_sap_hana():
""" Detect SAP HANA based on existance of /hana/shared/*/exe/linuxx86_64/hdb/sapcontrol """
"""
Detect SAP HANA based on existance of /hana/shared/*/exe/linuxx86_64/hdb/sapcontrol
"""
if os.path.exists(HANA_BASE_PATH):
for entry in os.listdir(HANA_BASE_PATH):
# Does /hana/shared/{entry}/exe/linuxx86_64/hdb/sapcontrol exist?
Expand All @@ -91,7 +124,9 @@ def detect_sap_hana():


def get_upgrade_flavour():
""" Returns the flavour of the upgrade for this system."""
"""
Returns the flavour of the upgrade for this system.
"""
if detect_sap_hana():
return LEAPP_UPGRADE_FLAVOUR_SAP_HANA
return LEAPP_UPGRADE_FLAVOUR_DEFAULT
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
NAME="Red Hat Enterprise Linux"
VERSION="8.5 (Ootpa)"
ID="rhel"
ID_LIKE="fedora"
VERSION_ID="8.5"
PLATFORM_ID="platform:el8"
PRETTY_NAME="Red Hat Enterprise Linux 8.5 Beta (Ootpa)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:redhat:enterprise_linux:8::baseos"
HOME_URL="https://www.redhat.com/"
DOCUMENTATION_URL="https://access.redhat.com/documentation/red_hat_enterprise_linux/8/"
BUG_REPORT_URL="https://bugzilla.redhat.com/"

REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 8"
REDHAT_BUGZILLA_PRODUCT_VERSION=8.5
REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux"
REDHAT_SUPPORT_PRODUCT_VERSION="8.5 Beta"
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ def _raise_call_error(*args):
)


def _get_os_release(version='7.9', codename='Maipo'):
release = OSRelease(
release_id='rhel',
name='Red Hat Enterprise Linux Server',
pretty_name='Red Hat Enterprise Linux',
version='{} ({})'.format(version, codename),
version_id='{}'.format(version),
variant='Server',
variant_id='server')
return release


def test_leapp_env_vars(monkeypatch):
_clean_leapp_envs(monkeypatch)
monkeypatch.setenv('LEAPP_WHATEVER', '0')
Expand All @@ -42,24 +54,24 @@ def test_leapp_env_vars(monkeypatch):


def test_get_target_version(monkeypatch):
valid_release = _get_os_release(version='8.6', codename='Ootpa').version_id

monkeypatch.delenv('LEAPP_DEVEL_TARGET_RELEASE', raising=False)
assert ipuworkflowconfig.get_target_version() == ipuworkflowconfig.CURRENT_TARGET_VERSION
monkeypatch.setattr(ipuworkflowconfig, 'get_os_release', lambda x: _get_os_release('8.6', 'Ootpa'))
assert ipuworkflowconfig.get_target_version() == ipuworkflowconfig.upgrade_paths_map[(valid_release, 'default')]
monkeypatch.setenv('LEAPP_DEVEL_TARGET_RELEASE', '')
assert ipuworkflowconfig.get_target_version() == ipuworkflowconfig.CURRENT_TARGET_VERSION
monkeypatch.setattr(ipuworkflowconfig, 'get_os_release', lambda x: _get_os_release('8.6', 'Ootpa'))
assert ipuworkflowconfig.get_target_version() == ipuworkflowconfig.upgrade_paths_map[(valid_release, 'default')]
monkeypatch.setenv('LEAPP_DEVEL_TARGET_RELEASE', '1.2.3')
assert ipuworkflowconfig.get_target_version() == '1.2.3'
monkeypatch.delenv('LEAPP_DEVEL_TARGET_RELEASE', raising=True)
# unsupported path
monkeypatch.setattr(ipuworkflowconfig, 'get_os_release', lambda x: _get_os_release('8.5', 'Ootpa'))
assert ipuworkflowconfig.get_target_version() == ipuworkflowconfig.upgrade_paths_map[(valid_release, 'default')]


def test_get_os_release_info(monkeypatch):
expected = OSRelease(
release_id='rhel',
name='Red Hat Enterprise Linux Server',
pretty_name='Red Hat Enterprise Linux',
version='7.6 (Maipo)',
version_id='7.6',
variant='Server',
variant_id='server')
expected = _get_os_release('7.6')
assert expected == ipuworkflowconfig.get_os_release(os.path.join(CUR_DIR, 'files/os-release'))

with pytest.raises(StopActorExecutionError):
Expand Down
2 changes: 2 additions & 0 deletions repos/system_upgrade/common/libraries/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
install-deps:
yum install -y python*-pyudev
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def parse_repofile(repofile):
def get_repodirs():
"""
Return all directories yum scans for repository files, if they exist.
By default, the possible paths on RHEL 7 should be:
By default, the possible paths on RHEL should be:
['/etc/yum.repos.d', '/etc/yum/repos.d', '/etc/distro.repos.d']
ATTENTION: Requires the dnf module to be present.
Expand Down
19 changes: 19 additions & 0 deletions repos/system_upgrade/common/models/dracutmodule.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from leapp.models import Model, fields
from leapp.topics import BootPrepTopic


class UpgradeDracutModule(Model):
"""
This model is used to influence the leapp upgrade initram disk generation by allowing to
include dracut modules specified by this message.
"""
topic = BootPrepTopic

name = fields.String()
""" Name of the dracut module that should be added (--add option of dracut) """

module_path = fields.Nullable(fields.String(default=None))
"""
module_path specifies dracut modules that are to be copied
If the path is not set, the given name will just be activated.
"""
Loading

0 comments on commit 0eca81c

Please sign in to comment.