Skip to content

Commit

Permalink
Merge pull request #4 from oamg/update-preupgrade-task-reporting
Browse files Browse the repository at this point in the history
Add alert and error fields to output (same as for pre-conversion)
  • Loading branch information
andywaltlova authored Nov 21, 2023
2 parents 1f427e2 + edad91c commit d89edef
Show file tree
Hide file tree
Showing 11 changed files with 240 additions and 155 deletions.
8 changes: 8 additions & 0 deletions schemas/preupgrade_schema_1.0.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
"description": "Script is expected to set up Leapp and run pre-upgrade analysis. This schema defines the output format that is expected by Red Hat Insights Task UI.",
"type": "object",
"properties": {
"alert": {
"type": "boolean"
},
"error": {
"type": "boolean"
},
"status": {
"$ref": "#/$defs/status_codes"
},
Expand Down Expand Up @@ -40,6 +46,8 @@
}
},
"required": [
"alert",
"error",
"status",
"message",
"report",
Expand Down
254 changes: 146 additions & 108 deletions scripts/leapp_preupgrade.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,30 @@
class ProcessError(Exception):
"""Custom exception to report errors during setup and run of leapp"""

def __init__(self, message):
super(ProcessError, self).__init__(message)
def __init__(self, message, report):
super(ProcessError, self).__init__(report)
self.message = message
self.report = report


class OutputCollector(object):
"""Wrapper class for script expected stdout"""

def __init__(self, status="", message="", report="", entries=None):
# pylint: disable=too-many-instance-attributes
# pylint: disable=too-many-arguments
# Nine and six is reasonable in this case.

def __init__(
self, status="", message="", report="", entries=None, alert=False, error=False
):
self.status = status
self.alert = alert # true if error true or if pre-upgrade inhibited

# NOTE: currently false everywhere
# here for consistency with conversions scripts
# expected to change after tasks implement new statuses
self.error = error

self.message = message
self.report = report
self.tasks_format_version = "1.0"
Expand All @@ -56,6 +70,8 @@ def to_dict(self):

return {
"status": self.status,
"alert": self.alert,
"error": self.error,
"message": self.message,
"report": self.report,
"report_json": self.report_json,
Expand Down Expand Up @@ -125,37 +141,102 @@ def run_subprocess(cmd, print_cmd=True, env=None, wait=True):
return output, process.returncode


def check_if_package_installed(pkg_name):
_, return_code = run_subprocess(["rpm", "-q", pkg_name])
def _check_if_package_installed(pkg_name):
_, return_code = run_subprocess(["/usr/bin/rpm", "-q", pkg_name])
return return_code == 0


def setup_leapp(command, rhui_pkgs):
def _get_leapp_command_and_packages(version):
if version.startswith("7"):
leapp_install_command = [
"/usr/bin/yum",
"install",
"leapp-upgrade",
"-y",
"--enablerepo=rhel-7-server-extras-rpms",
]
rhui_packages = [
{"src_pkg": "rh-amazon-rhui-client", "leapp_pkg": "leapp-rhui-aws"},
{
"src_pkg": "rh-amazon-rhui-client-sap-bundle",
"leapp_pkg": "leapp-rhui-aws-sap-e4s",
},
{"src_pkg": "rhui-azure-rhel7", "leapp_pkg": "leapp-rhui-azure"},
{
"src_pkg": "rhui-azure-rhel7-base-sap-apps",
"leapp_pkg": "leapp-rhui-azure-sap",
},
{
"src_pkg": "rhui-azure-rhel7-base-sap-ha",
"leapp_pkg": "leapp-rhui-azure-sap",
},
{
"src_pkg": "google-rhui-client-rhel7",
"leapp_pkg": "leapp-rhui-google",
},
{
"src_pkg": "google-rhui-client-rhel79-sap",
"leapp_pkg": "leapp-rhui-google-sap",
},
]
if version.startswith("8"):
leapp_install_command = ["/usr/bin/dnf", "install", "leapp-upgrade", "-y"]
rhui_packages = [
{"src_pkg": "rh-amazon-rhui-client", "leapp_pkg": "leapp-rhui-aws"},
{
"src_pkg": "rh-amazon-rhui-client-sap-bundle-e4s",
"leapp_pkg": "leapp-rhui-aws-sap-e4s",
},
{"src_pkg": "rhui-azure-rhel8", "leapp_pkg": "leapp-rhui-azure"},
{
"src_pkg": "rhui-azure-rhel8-eus",
"leapp_pkg": "leapp-rhui-azure-eus",
},
{
"src_pkg": "rhui-azure-rhel8-sap-ha",
"leapp_pkg": "leapp-rhui-azure-sap",
},
{
"src_pkg": "rhui-azure-rhel8-sapapps",
"leapp_pkg": "leapp-rhui-azure-sap",
},
{
"src_pkg": "google-rhui-client-rhel8",
"leapp_pkg": "leapp-rhui-google",
},
{
"src_pkg": "google-rhui-client-rhel8-sap",
"leapp_pkg": "leapp-rhui-google-sap",
},
]
return leapp_install_command, rhui_packages


def setup_leapp(version):
print("Installing leapp ...")
output, returncode = run_subprocess(command)
leapp_install_command, rhel_rhui_packages = _get_leapp_command_and_packages(version)
output, returncode = run_subprocess(leapp_install_command)
if returncode:
print(
"Installation of leapp failed with code '%s' and output: %s\n"
% (returncode, output)
)
raise ProcessError(
message="Installation of leapp failed with code '%s'." % returncode
message="Installation of leapp failed",
report="Installation of leapp failed with code '%s' and output: %s."
% (returncode, output.rstrip("\n")),
)

print("Check installed rhui packages ...")
for pkg in rhui_pkgs:
if check_if_package_installed(pkg["src_pkg"]):
for pkg in rhel_rhui_packages:
if _check_if_package_installed(pkg["src_pkg"]):
pkg["installed"] = True
return [pkg for pkg in rhui_pkgs if pkg.get("installed", False)]
return [pkg for pkg in rhel_rhui_packages if pkg.get("installed", False)]


def should_use_no_rhsm_check(rhui_installed, command):
print("Checking if subscription manager and repositories are available ...")
rhsm_repo_check_fail = True
_, rhsm_installed_check = run_subprocess(["which", "subscription-manager"])
if rhsm_installed_check == 0:
rhsm_installed_check = _check_if_package_installed("subscription-manager")
if rhsm_installed_check:
rhsm_repo_check, _ = run_subprocess(
["subscription-manager", "repos", "--list-enabled"]
["/usr/sbin/subscription-manager", "repos", "--list-enabled"]
)
rhsm_repo_check_fail = (
"This system has no repositories available through subscriptions."
Expand All @@ -175,13 +256,13 @@ def install_leapp_pkg_corresponding_to_installed_rhui(rhui_pkgs):
for pkg in rhui_pkgs:
install_pkg = pkg["leapp_pkg"]
install_output, returncode = run_subprocess(
["yum", "install", "-y", install_pkg]
["/usr/bin/yum", "install", "-y", install_pkg]
)
if returncode:
print("Installation of %s failed. \n%s" % (install_pkg, install_output))
raise ProcessError(
message="Installation of %s (coresponding pkg to '%s') failed with exit code %s."
% (install_pkg, pkg, returncode)
message="Installation of %s (coresponding pkg to '%s') failed",
report="Installation of %s (coresponding pkg to '%s') failed with exit code %s and output: %s."
% (install_pkg, pkg, returncode, install_output.rstrip("\n")),
)


Expand All @@ -208,7 +289,7 @@ def execute_preupgrade(command):
# raise ProcessError(message="Leapp exited with code '%s'." % returncode)


def find_highest_report_level(entries):
def _find_highest_report_level(entries):
"""
Gather status codes from entries.
"""
Expand Down Expand Up @@ -248,7 +329,7 @@ def parse_results(output):
)
alert = inhibitor_count > 0
status = (
find_highest_report_level(report_entries)
_find_highest_report_level(report_entries)
if len(report_entries) > 0
else "SUCCESS"
)
Expand All @@ -267,111 +348,68 @@ def parse_results(output):
output.report = report_txt


def call_insights_client():
print("Calling insight-client in background for immediate data collection.")
run_subprocess(["insights-client"], wait=False)
# NOTE: we do not care about returncode or output because we are not waiting for process to finish

def update_insights_inventory():
"""Call insights-client to update insights inventory."""
print("Updating system status in Red Hat Insights.")
output, returncode = run_subprocess(cmd=["/usr/bin/insights-client"])

def main():
# Exit if not RHEL 7 or 8
dist, version = get_rhel_version()
if dist != "rhel" or is_non_eligible_releases(version):
if returncode:
raise ProcessError(
message='Exiting because distribution="%s" and version="%s"'
% (dist, version)
message="Failed to update Insights Inventory by registering the system again. See output the following output: %s"
% output,
report="insights-client execution exited with code '%s'." % returncode,
)

output = OutputCollector()
print("System registered with insights-client successfully.")


def main():
try:
# Init variables
# Exit if not RHEL 7 or 8
dist, version = get_rhel_version()
if dist != "rhel" or is_non_eligible_releases(version):
raise ProcessError(
message="In-place upgrades are supported only on RHEL distributions.",
report='Exiting because distribution="%s" and version="%s"'
% (dist, version),
)

output = OutputCollector()
preupgrade_command = ["/usr/bin/leapp", "preupgrade", "--report-schema=1.1.0"]
use_no_rhsm = False
rhui_pkgs = []
if version.startswith("7"):
leapp_install_command = [
"yum",
"install",
"leapp-upgrade",
"-y",
"--enablerepo=rhel-7-server-extras-rpms",
]
rhel_7_rhui_packages = [
{"src_pkg": "rh-amazon-rhui-client", "leapp_pkg": "leapp-rhui-aws"},
{
"src_pkg": "rh-amazon-rhui-client-sap-bundle",
"leapp_pkg": "leapp-rhui-aws-sap-e4s",
},
{"src_pkg": "rhui-azure-rhel7", "leapp_pkg": "leapp-rhui-azure"},
{
"src_pkg": "rhui-azure-rhel7-base-sap-apps",
"leapp_pkg": "leapp-rhui-azure-sap",
},
{
"src_pkg": "rhui-azure-rhel7-base-sap-ha",
"leapp_pkg": "leapp-rhui-azure-sap",
},
{
"src_pkg": "google-rhui-client-rhel7",
"leapp_pkg": "leapp-rhui-google",
},
{
"src_pkg": "google-rhui-client-rhel79-sap",
"leapp_pkg": "leapp-rhui-google-sap",
},
]
rhui_pkgs = setup_leapp(leapp_install_command, rhel_7_rhui_packages)
if version.startswith("8"):
leapp_install_command = ["dnf", "install", "leapp-upgrade", "-y"]
rhel_8_rhui_packages = [
{"src_pkg": "rh-amazon-rhui-client", "leapp_pkg": "leapp-rhui-aws"},
{
"src_pkg": "rh-amazon-rhui-client-sap-bundle-e4s",
"leapp_pkg": "leapp-rhui-aws-sap-e4s",
},
{"src_pkg": "rhui-azure-rhel8", "leapp_pkg": "leapp-rhui-azure"},
{
"src_pkg": "rhui-azure-rhel8-eus",
"leapp_pkg": "leapp-rhui-azure-eus",
},
{
"src_pkg": "rhui-azure-rhel8-sap-ha",
"leapp_pkg": "leapp-rhui-azure-sap",
},
{
"src_pkg": "rhui-azure-rhel8-sapapps",
"leapp_pkg": "leapp-rhui-azure-sap",
},
{
"src_pkg": "google-rhui-client-rhel8",
"leapp_pkg": "leapp-rhui-google",
},
{
"src_pkg": "google-rhui-client-rhel8-sap",
"leapp_pkg": "leapp-rhui-google-sap",
},
]
rhui_pkgs = setup_leapp(leapp_install_command, rhel_8_rhui_packages)
rhui_pkgs = setup_leapp(version)

# Check for RHUI PKGs
use_no_rhsm = should_use_no_rhsm_check(len(rhui_pkgs) > 1, preupgrade_command)

if use_no_rhsm:
install_leapp_pkg_corresponding_to_installed_rhui(rhui_pkgs)

remove_previous_reports()
execute_preupgrade(preupgrade_command)
print("Pre-upgrade successfully executed.")
parse_results(output)
update_insights_inventory()
print("Pre-upgrade successfully executed.")
except ProcessError as exception:
output = OutputCollector(status="ERROR", report=exception.message)
print(exception.report)
output = OutputCollector(
status="ERROR",
alert=True,
error=False,
message=exception.message,
report=exception.report,
)
except Exception as exception:
output = OutputCollector(status="ERROR", report=str(exception))
print(str(exception))
output = OutputCollector(
status="ERROR",
alert=True,
error=False,
message="An unexpected error occurred. Expand the row for more details.",
report=str(exception),
)
finally:
print("### JSON START ###")
print(json.dumps(output.to_dict(), indent=4))
print("### JSON END ###")
call_insights_client()


if __name__ == "__main__":
Expand Down
6 changes: 3 additions & 3 deletions tests/preupgrade/test_check_pkg_installed.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from mock import patch

from scripts.leapp_preupgrade import check_if_package_installed
from scripts.leapp_preupgrade import _check_if_package_installed


@patch("scripts.leapp_preupgrade.run_subprocess")
def test_check_if_package_installed(mock_run_subprocess):
pkg_name = "example-package"
mock_run_subprocess.return_value = ("", 0)
result = check_if_package_installed(pkg_name)
expected_command = ["rpm", "-q", pkg_name]
result = _check_if_package_installed(pkg_name)
expected_command = ["/usr/bin/rpm", "-q", pkg_name]
mock_run_subprocess.assert_called_once_with(expected_command)
assert result
Loading

0 comments on commit d89edef

Please sign in to comment.