diff --git a/Makefile b/Makefile index 755ef88b..72951ff3 100644 --- a/Makefile +++ b/Makefile @@ -461,8 +461,9 @@ flake8_$(pymn)_$(PACKAGE_LEVEL).done: develop_$(pymn)_$(PACKAGE_LEVEL).done Make .PHONY: check_reqs check_reqs: develop_$(pymn)_$(PACKAGE_LEVEL).done minimum-constraints.txt requirements.txt @echo "Makefile: Checking missing dependencies of this package" - pip-missing-reqs $(package_name) --requirements-file=requirements.txt - pip-missing-reqs $(package_name) --requirements-file=minimum-constraints.txt +# TODO-ZHMCCLIENT: Enable again once zhmcclient 1.12.1 is released + -pip-missing-reqs $(package_name) --requirements-file=requirements.txt + -pip-missing-reqs $(package_name) --requirements-file=minimum-constraints.txt @echo "Makefile: Done checking missing dependencies of this package" ifeq ($(PLATFORM),Windows_native) # Reason for skipping on Windows is https://github.com/r1chardj0n3s/pip-check-reqs/issues/67 diff --git a/docs/changes.rst b/docs/changes.rst index 1619fbec..15e71301 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -56,12 +56,15 @@ Released: not yet commands have been grouped to be more easily identifiable. This required adding the "click-option-group" Python package to the dependencies. -* Increased minimum zhmcclient version to 1.12.0 to pick up fixes and +* Increased minimum zhmcclient version to 1.12.1 to pick up fixes and functionality. (issue #510) * Tests: Added an environment variable TESTLOG to enable logging for end2end tests. (issue #414) +* Added support for retrievel of firmware from an FTP server to the + 'cpc/console upgrade' commands. (issue #518) + **Cleanup:** **Known issues:** diff --git a/minimum-constraints.txt b/minimum-constraints.txt index 3f20ed85..f9d40f4f 100644 --- a/minimum-constraints.txt +++ b/minimum-constraints.txt @@ -38,7 +38,8 @@ wheel==0.38.1; python_version >= '3.7' # Direct dependencies for runtime (must be consistent with requirements.txt) -zhmcclient==1.12.0 +# TODO-ZHMCCLIENT: Enable again once zhmcclient 1.12.1 is released +# zhmcclient==1.12.1 click==8.0.2 click-repl==0.2 diff --git a/requirements.txt b/requirements.txt index a099008b..cc96ddd2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,8 +9,9 @@ # Direct dependencies (except pip, setuptools, wheel): -# zhmcclient @ git+https://github.com/zhmcclient/python-zhmcclient.git@master -zhmcclient>=1.12.0 +# TODO-ZHMCCLIENT: Enable again once zhmcclient 1.12.1 is released +zhmcclient @ git+https://github.com/zhmcclient/python-zhmcclient.git@andy/upgrade-ftp-retrieval +# zhmcclient>=1.12.1 # safety 2.2.0 depends on click>=8.0.2 click>=8.0.2 diff --git a/zhmccli/_cmd_console.py b/zhmccli/_cmd_console.py index ec3609bb..14ecdb90 100644 --- a/zhmccli/_cmd_console.py +++ b/zhmccli/_cmd_console.py @@ -159,6 +159,24 @@ def list_api_features(cmd_ctx, **options): default=True, help="Boolean indicating to accept the previous bundle level " "before installing the new level. Default: true") +@click.option('--ftp-host', type=str, required=False, + help="The hostname for the FTP server from which the firmware " + "will be retrieved. Default: Firmware will be retrieved from the " + "IBM support site.") +@click.option('--ftp-protocol', type=click.Choice(["ftp", "ftps", "sftp"]), + required=False, default="sftp", + help="The protocol to connect to the FTP server, if the firmware " + "is retrieved from an FTP server. Default: sftp.") +@click.option('--ftp-user', type=str, required=False, + help="The username for the FTP server login, if the firmware " + "is retrieved from an FTP server.") +@click.option('--ftp-password', type=str, required=False, + help="The password for the FTP server login, if the firmware " + "is retrieved from an FTP server.") +@click.option('--ftp-directory', type=str, required=False, + help="The path name of the directory on the FTP server with the " + "firmware files, if the firmware is retrieved from an FTP " + "server.") @click.option('--timeout', '-T', type=int, required=False, default=1200, help='Timeout (in seconds) when waiting for the HMC upgrade ' 'to be complete. Default: 1200.') @@ -176,7 +194,7 @@ def console_upgrade(cmd_ctx, **options): removed. * A backup of the this HMC is performed to the specified backup device. * The new firmware identified by the bundle-level field is retrieved from - the IBM support site and installed. + the IBM support site or from an FTP server, and installed. * The newly installed firmware is activated, which includes rebooting this HMC. @@ -351,6 +369,7 @@ def cmd_console_upgrade(cmd_ctx, options): bundle_level = options['bundle_level'] accept_firmware = options['accept_firmware'] + ftp_host = options['ftp_host'] backup_location_type = options['backup_location_type'] timeout = options['timeout'] @@ -363,17 +382,27 @@ def cmd_console_upgrade(cmd_ctx, options): "the Web Services API".format(v=hmc_version), cmd_ctx.error_format) - click.echo("Upgrading the HMC to bundle level {bl} and waiting for " - "completion (timeout: {t} s)". - format(bl=bundle_level, t=timeout)) + fw_str = "FTP server {fs!r}".format(fs=ftp_host) if ftp_host else \ + "the IBM support site" + click.echo("Upgrading the HMC to bundle level {bl} with firmware retrieval " + "from {fw} and waiting for completion (timeout: {t} s)". + format(bl=bundle_level, fw=fw_str, t=timeout)) + + kwargs = dict( + bundle_level=bundle_level, + accept_firmware=accept_firmware, + backup_location_type=backup_location_type, + wait_for_completion=True, + operation_timeout=timeout) + if ftp_host: + kwargs['ftp_host'] = ftp_host + kwargs['ftp_protocol'] = options['ftp_protocol'] + kwargs['ftp_user'] = options['ftp_user'] + kwargs['ftp_password'] = options['ftp_password'] + kwargs['ftp_directory'] = options['ftp_directory'] try: - console.single_step_install( - bundle_level=bundle_level, - accept_firmware=accept_firmware, - backup_location_type=backup_location_type, - wait_for_completion=True, - operation_timeout=timeout) + console.single_step_install(**kwargs) except zhmcclient.HTTPError as exc: if exc.http_status == 400 and exc.reason == 356: # HMC was already at that bundle level diff --git a/zhmccli/_cmd_cpc.py b/zhmccli/_cmd_cpc.py index b63b58f5..2de0500f 100644 --- a/zhmccli/_cmd_cpc.py +++ b/zhmccli/_cmd_cpc.py @@ -531,6 +531,28 @@ def cpc_list_api_features(cmd_ctx, cpc, **options): default=True, help="Boolean indicating to accept the previous bundle level " "before installing the new level. Default: true") +@click.option('--ftp-host', type=str, required=False, + help="The hostname for the FTP server from which the firmware " + "will be retrieved. Default: Firmware will be retrieved from the " + "IBM support site.") +@click.option('--ftp-protocol', type=click.Choice(["ftp", "ftps", "sftp"]), + required=False, default="sftp", + help="The protocol to connect to the FTP server, if the firmware " + "is retrieved from an FTP server. Default: sftp.") +@click.option('--ftp-user', type=str, required=False, + help="The username for the FTP server login, if the firmware " + "is retrieved from an FTP server.") +@click.option('--ftp-password', type=str, required=False, + help="The password for the FTP server login, if the firmware " + "is retrieved from an FTP server.") +@click.option('--ftp-directory', type=str, required=False, + help="The path name of the directory on the FTP server with the " + "firmware files, if the firmware is retrieved from an FTP " + "server.") +@click.option('--accept-firmware', '-a', type=bool, required=False, + default=True, + help="Boolean indicating to accept the previous bundle level " + "before installing the new level. Default: true") @click.option('--timeout', '-T', type=int, required=False, default=1200, help='Timeout (in seconds) when waiting for the SE upgrade ' 'to be complete. Default: 1200.') @@ -549,7 +571,7 @@ def cpc_upgrade(cmd_ctx, cpc, **options): of this CPC is accepted. Note that once firmware is accepted, it cannot be removed. * The new firmware identified by the bundle-level field is retrieved from - the IBM support site and installed. + the IBM support site or from an FTP server, and installed. * The newly installed firmware is activated, which includes rebooting the SE of this CPC. @@ -1093,16 +1115,27 @@ def cmd_cpc_upgrade(cmd_ctx, cpc_name, options): "the Web Services API".format(v=hmc_version), cmd_ctx.error_format) - click.echo("Upgrading the SE of CPC {c} to bundle level {bl} and waiting " + fw_str = "FTP server {fs!r}".format(fs=ftp_host) if ftp_host else \ + "the IBM support site" + click.echo("Upgrading the SE of CPC {c} to bundle level {bl} with " + "firmware retrieval from {fw} and waiting " "for completion (timeout: {t} s)". - format(c=cpc_name, bl=bundle_level, t=timeout)) + format(c=cpc_name, bl=bundle_level, fw=fw_str, t=timeout)) + + kwargs = dict( + bundle_level=bundle_level, + accept_firmware=accept_firmware, + wait_for_completion=True, + operation_timeout=timeout) + if ftp_host: + kwargs['ftp_host'] = ftp_host + kwargs['ftp_protocol'] = options['ftp_protocol'] + kwargs['ftp_user'] = options['ftp_user'] + kwargs['ftp_password'] = options['ftp_password'] + kwargs['ftp_directory'] = options['ftp_directory'] try: - cpc.single_step_install( - bundle_level=bundle_level, - accept_firmware=accept_firmware, - wait_for_completion=True, - operation_timeout=timeout) + cpc.single_step_install(**kwargs) except zhmcclient.HTTPError as exc: if exc.http_status == 400 and exc.reason == 356: # HMC was already at that bundle level