|
2 | 2 | import itertools |
3 | 3 | import json |
4 | 4 | import os |
| 5 | +import sys |
5 | 6 | import shutil |
6 | 7 | import tarfile |
| 8 | +import six.moves |
7 | 9 | from datetime import datetime |
| 10 | +from contextlib import contextmanager |
| 11 | +import six |
8 | 12 |
|
9 | 13 | from leapp.cli.commands import command_utils |
10 | 14 | from leapp.cli.commands.config import get_config |
11 | | -from leapp.exceptions import CommandError |
| 15 | +from leapp.exceptions import CommandError, LeappRuntimeError |
12 | 16 | from leapp.repository.scan import find_and_scan_repositories |
13 | 17 | from leapp.utils import audit |
14 | 18 | from leapp.utils.audit import get_checkpoints, get_connection, get_messages |
15 | | -from leapp.utils.output import report_unsupported |
| 19 | +from leapp.utils.output import report_unsupported, pretty_block_text, pretty_block, Color |
16 | 20 | from leapp.utils.report import fetch_upgrade_report_messages, generate_report_file |
| 21 | +from leapp.models import ErrorModel |
| 22 | + |
| 23 | + |
17 | 24 |
|
18 | 25 |
|
19 | 26 | def disable_database_sync(): |
@@ -167,6 +174,46 @@ def warn_if_unsupported(configuration): |
167 | 174 | report_unsupported(devel_vars, configuration["whitelist_experimental"]) |
168 | 175 |
|
169 | 176 |
|
| 177 | +def ask_to_continue(): |
| 178 | + """ |
| 179 | + Pause before starting the upgrade, warn the user about potential conseqences |
| 180 | + and ask for confirmation. |
| 181 | + Only done on whitelisted OS. |
| 182 | +
|
| 183 | + :return: True if it's OK to continue, False if the upgrade should be interrupted. |
| 184 | + """ |
| 185 | + |
| 186 | + ask_on_os = ['cloudlinux'] |
| 187 | + os_id = command_utils.get_os_release_id('/etc/os-release') |
| 188 | + |
| 189 | + if os_id not in ask_on_os: |
| 190 | + return True |
| 191 | + |
| 192 | + with pretty_block( |
| 193 | + text="Upgrade workflow initiated", |
| 194 | + end_text="Continue?", |
| 195 | + target=sys.stdout, |
| 196 | + color=Color.bold, |
| 197 | + ): |
| 198 | + warn_msg = ( |
| 199 | + "Past this point, Leapp will begin making changes to your system.\n" |
| 200 | + "An improperly or incompletely configured upgrade may break the system, " |
| 201 | + "up to and including making it *completely inaccessible*.\n" |
| 202 | + "Even if you've followed all the preparation steps correctly, " |
| 203 | + "the chance of the upgrade going wrong remains non-zero.\n" |
| 204 | + "Make sure you've run the pre-check and checked the logs and reports.\n" |
| 205 | + "Do you confirm that you've successfully taken and tested a full backup of your server?\n" |
| 206 | + "Rollback will not be possible." |
| 207 | + ) |
| 208 | + print(warn_msg) |
| 209 | + |
| 210 | + response = "" |
| 211 | + while response not in ["y", "n"]: |
| 212 | + response = six.moves.input("Y/N> ").lower() |
| 213 | + |
| 214 | + return response == "y" |
| 215 | + |
| 216 | + |
170 | 217 | def handle_output_level(args): |
171 | 218 | """ |
172 | 219 | Set environment variables following command line arguments. |
@@ -247,3 +294,68 @@ def process_whitelist_experimental(repositories, workflow, configuration, logger |
247 | 294 | if logger: |
248 | 295 | logger.error(msg) |
249 | 296 | raise CommandError(msg) |
| 297 | + |
| 298 | + |
| 299 | +def process_report_schema(args, configuration): |
| 300 | + default_report_schema = configuration.get('report', 'schema') |
| 301 | + if args.report_schema and args.report_schema > default_report_schema: |
| 302 | + raise CommandError('--report-schema version can not be greater that the ' |
| 303 | + 'actual {} one.'.format(default_report_schema)) |
| 304 | + return args.report_schema or default_report_schema |
| 305 | + |
| 306 | + |
| 307 | +# TODO: This and the following functions should eventually be placed into the |
| 308 | +# leapp.utils.output module. |
| 309 | +def pretty_block_log(string, logger_level, width=60): |
| 310 | + log_str = "\n{separator}\n{text}\n{separator}\n".format( |
| 311 | + separator="=" * width, |
| 312 | + text=string.center(width)) |
| 313 | + logger_level(log_str) |
| 314 | + |
| 315 | + |
| 316 | +@contextmanager |
| 317 | +def format_actor_exceptions(logger): |
| 318 | + try: |
| 319 | + try: |
| 320 | + yield |
| 321 | + except LeappRuntimeError as err: |
| 322 | + msg = "{} - Please check the above details".format(err.message) |
| 323 | + sys.stderr.write("\n") |
| 324 | + sys.stderr.write(pretty_block_text(msg, color="", width=len(msg))) |
| 325 | + logger.error(err.message) |
| 326 | + finally: |
| 327 | + pass |
| 328 | + |
| 329 | + |
| 330 | +def log_errors(errors, logger): |
| 331 | + if errors: |
| 332 | + pretty_block_log("ERRORS", logger.info) |
| 333 | + |
| 334 | + for error in errors: |
| 335 | + model = ErrorModel.create(json.loads(error['message']['data'])) |
| 336 | + error_message = model.message |
| 337 | + if six.PY2: |
| 338 | + error_message = model.message.encode('utf-8', 'xmlcharrefreplace') |
| 339 | + |
| 340 | + logger.error("{time} [{severity}] Actor: {actor}\nMessage: {message}\n".format( |
| 341 | + severity=model.severity.upper(), |
| 342 | + message=error_message, time=model.time, actor=model.actor)) |
| 343 | + if model.details: |
| 344 | + print('Summary:') |
| 345 | + details = json.loads(model.details) |
| 346 | + for detail in details: |
| 347 | + print(' {k}: {v}'.format( |
| 348 | + k=detail.capitalize(), |
| 349 | + v=details[detail].rstrip().replace('\n', '\n' + ' ' * (6 + len(detail))))) |
| 350 | + |
| 351 | + |
| 352 | +def log_inhibitors(context_id, logger): |
| 353 | + from leapp.reporting import Flags # pylint: disable=import-outside-toplevel |
| 354 | + reports = fetch_upgrade_report_messages(context_id) |
| 355 | + inhibitors = [report for report in reports if Flags.INHIBITOR in report.get('flags', [])] |
| 356 | + if inhibitors: |
| 357 | + pretty_block_log("UPGRADE INHIBITED", logger.error) |
| 358 | + logger.error('Upgrade has been inhibited due to the following problems:') |
| 359 | + for position, report in enumerate(inhibitors, start=1): |
| 360 | + logger.error('{idx:5}. Inhibitor: {title}'.format(idx=position, title=report['title'])) |
| 361 | + logger.info('Consult the pre-upgrade report for details and possible remediation.') |
0 commit comments