diff options
| author | Zuul <zuul@review.opendev.org> | 2022-12-05 12:59:52 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2022-12-05 12:59:52 +0000 |
| commit | 29129a7715feb750b7738a5884f9d2f49491a511 (patch) | |
| tree | ce638cf37587869c165ac958ab56fa2f7801a43c /openstackclient/image | |
| parent | 8248efa8d9f264bdeb267d3eb666d87edf9b7574 (diff) | |
| parent | 4eea3408dc492e948671b625ffc4379212b5857c (diff) | |
| download | python-openstackclient-29129a7715feb750b7738a5884f9d2f49491a511.tar.gz | |
Merge "image: Add 'image import' command"
Diffstat (limited to 'openstackclient/image')
| -rw-r--r-- | openstackclient/image/v2/image.py | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/openstackclient/image/v2/image.py b/openstackclient/image/v2/image.py index 737cf324..21b962f1 100644 --- a/openstackclient/image/v2/image.py +++ b/openstackclient/image/v2/image.py @@ -22,6 +22,7 @@ import os import sys from cinderclient import api_versions +from openstack import exceptions as sdk_exceptions from openstack.image import image_signer from osc_lib.api import utils as api_utils from osc_lib.cli import format_columns @@ -1557,3 +1558,245 @@ class StageImage(command.Command): kwargs['data'] = fp image_client.stage_image(image, **kwargs) + + +class ImportImage(command.ShowOne): + _description = _( + "Initiate the image import process.\n" + "This requires support for the interoperable image import process, " + "which was first introduced in Image API version 2.6 " + "(Glance 16.0.0 (Queens))" + ) + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + + parser.add_argument( + 'image', + metavar='<image>', + help=_('Image to initiate import process for (name or ID)'), + ) + # TODO(stephenfin): Uncomment help text when we have this command + # implemented + parser.add_argument( + '--method', + metavar='<method>', + default='glance-direct', + dest='import_method', + choices=[ + 'glance-direct', + 'web-download', + 'glance-download', + 'copy-image', + ], + help=_( + "Import method used for image import process. " + "Not all deployments will support all methods. " + # "Valid values can be retrieved with the 'image import " + # "methods' command. " + "The 'glance-direct' method (default) requires images be " + "first staged using the 'image-stage' command." + ), + ) + parser.add_argument( + '--uri', + metavar='<uri>', + help=_( + "URI to download the external image " + "(only valid with the 'web-download' import method)" + ), + ) + parser.add_argument( + '--remote-image', + metavar='<REMOTE_IMAGE>', + help=_( + "The image of remote glance (ID only) to be imported " + "(only valid with the 'glance-download' import method)" + ), + ) + parser.add_argument( + '--remote-region', + metavar='<REMOTE_GLANCE_REGION>', + help=_( + "The remote Glance region to download the image from " + "(only valid with the 'glance-download' import method)" + ), + ) + parser.add_argument( + '--remote-service-interface', + metavar='<REMOTE_SERVICE_INTERFACE>', + help=_( + "The remote Glance service interface to use when importing " + "images " + "(only valid with the 'glance-download' import method)" + ), + ) + stores_group = parser.add_mutually_exclusive_group() + stores_group.add_argument( + '--store', + metavar='<STORE>', + dest='stores', + nargs='*', + help=_( + "Backend store to upload image to " + "(specify multiple times to upload to multiple stores) " + "(either '--store' or '--all-stores' required with the " + "'copy-image' import method)" + ), + ) + stores_group.add_argument( + '--all-stores', + help=_( + "Make image available to all stores " + "(either '--store' or '--all-stores' required with the " + "'copy-image' import method)" + ), + ) + parser.add_argument( + '--allow-failure', + action='store_true', + dest='allow_failure', + default=True, + help=_( + 'When uploading to multiple stores, indicate that the import ' + 'should be continue should any of the uploads fail. ' + 'Only usable with --stores or --all-stores' + ), + ) + parser.add_argument( + '--disallow-failure', + action='store_true', + dest='allow_failure', + default=True, + help=_( + 'When uploading to multiple stores, indicate that the import ' + 'should be reverted should any of the uploads fail. ' + 'Only usable with --stores or --all-stores' + ), + ) + parser.add_argument( + '--wait', + action='store_true', + help=_('Wait for operation to complete'), + ) + return parser + + def take_action(self, parsed_args): + image_client = self.app.client_manager.image + + try: + import_info = image_client.get_import_info() + except sdk_exceptions.ResourceNotFound: + msg = _( + 'The Image Import feature is not supported by this deployment' + ) + raise exceptions.CommandError(msg) + + import_methods = import_info.import_methods['value'] + + if parsed_args.import_method not in import_methods: + msg = _( + "The '%s' import method is not supported by this deployment. " + "Supported: %s" + ) + raise exceptions.CommandError( + msg % (parsed_args.import_method, ', '.join(import_methods)), + ) + + if parsed_args.import_method == 'web-download': + if not parsed_args.uri: + msg = _( + "The '--uri' option is required when using " + "'--method=web-download'" + ) + raise exceptions.CommandError(msg) + else: + if parsed_args.uri: + msg = _( + "The '--uri' option is only supported when using " + "'--method=web-download'" + ) + raise exceptions.CommandError(msg) + + if parsed_args.import_method == 'glance-download': + if not (parsed_args.remote_region and parsed_args.remote_image): + msg = _( + "The '--remote-region' and '--remote-image' options are " + "required when using '--method=web-download'" + ) + raise exceptions.CommandError(msg) + else: + if parsed_args.remote_region: + msg = _( + "The '--remote-region' option is only supported when " + "using '--method=glance-download'" + ) + raise exceptions.CommandError(msg) + + if parsed_args.remote_image: + msg = _( + "The '--remote-image' option is only supported when using " + "'--method=glance-download'" + ) + raise exceptions.CommandError(msg) + + if parsed_args.remote_service_interface: + msg = _( + "The '--remote-service-interface' option is only " + "supported when using '--method=glance-download'" + ) + raise exceptions.CommandError(msg) + + if parsed_args.import_method == 'copy-image': + if not (parsed_args.stores or parsed_args.all_stores): + msg = _( + "The '--stores' or '--all-stores' options are required " + "when using '--method=copy-image'" + ) + raise exceptions.CommandError(msg) + + image = image_client.find_image(parsed_args.image) + + if not image.container_format and not image.disk_format: + msg = _( + "The 'container_format' and 'disk_format' properties " + "must be set on an image before it can be imported" + ) + raise exceptions.CommandError(msg) + + if parsed_args.import_method == 'glance-direct': + if image.status != 'uploading': + msg = _( + "The 'glance-direct' import method can only be used with " + "an image in status 'uploading'" + ) + raise exceptions.CommandError(msg) + elif parsed_args.import_method == 'web-download': + if image.status != 'queued': + msg = _( + "The 'web-download' import method can only be used with " + "an image in status 'queued'" + ) + raise exceptions.CommandError(msg) + elif parsed_args.import_method == 'copy-image': + if image.status != 'active': + msg = _( + "The 'copy-image' import method can only be used with " + "an image in status 'active'" + ) + raise exceptions.CommandError(msg) + + image_client.import_image( + image, + method=parsed_args.import_method, + # uri=parsed_args.uri, + # remote_region=parsed_args.remote_region, + # remote_image=parsed_args.remote_image, + # remote_service_interface=parsed_args.remote_service_interface, + stores=parsed_args.stores, + all_stores=parsed_args.all_stores, + all_stores_must_succeed=not parsed_args.allow_failure, + ) + + info = _format_image(image) + return zip(*sorted(info.items())) |
