diff options
Diffstat (limited to 'openstackclient/image')
| -rw-r--r-- | openstackclient/image/v2/image.py | 66 | ||||
| -rw-r--r-- | openstackclient/image/v2/metadef_namespaces.py | 247 |
2 files changed, 288 insertions, 25 deletions
diff --git a/openstackclient/image/v2/image.py b/openstackclient/image/v2/image.py index 21b962f1..4adaadda 100644 --- a/openstackclient/image/v2/image.py +++ b/openstackclient/image/v2/image.py @@ -33,7 +33,7 @@ from osc_lib import utils from openstackclient.common import progressbar from openstackclient.i18n import _ -from openstackclient.identity import common +from openstackclient.identity import common as identity_common if os.name == "nt": import msvcrt @@ -177,21 +177,22 @@ class AddProjectToImage(command.ShowOne): metavar="<project>", help=_("Project to associate with image (ID)"), ) - common.add_project_domain_option_to_parser(parser) + identity_common.add_project_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): image_client = self.app.client_manager.image identity_client = self.app.client_manager.identity - project_id = common.find_project( + project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, ).id image = image_client.find_image( - parsed_args.image, ignore_missing=False + parsed_args.image, + ignore_missing=False, ) obj = image_client.add_member( @@ -397,7 +398,7 @@ class CreateImage(command.ShowOne): "Force the use of glance image import instead of direct upload" ), ) - common.add_project_domain_option_to_parser(parser) + identity_common.add_project_domain_option_to_parser(parser) for deadopt in self.deadopts: parser.add_argument( "--%s" % deadopt, @@ -450,7 +451,7 @@ class CreateImage(command.ShowOne): kwargs['visibility'] = parsed_args.visibility if parsed_args.project: - kwargs['owner_id'] = common.find_project( + kwargs['owner_id'] = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, @@ -664,7 +665,8 @@ class DeleteImage(command.Command): for image in parsed_args.images: try: image_obj = image_client.find_image( - image, ignore_missing=False + image, + ignore_missing=False, ) image_client.delete_image(image_obj.id) except Exception as e: @@ -765,7 +767,7 @@ class ListImage(command.Lister): metavar='<project>', help=_("Search by project (admin only) (name or ID)"), ) - common.add_project_domain_option_to_parser(parser) + identity_common.add_project_domain_option_to_parser(parser) parser.add_argument( '--tag', metavar='<tag>', @@ -835,7 +837,10 @@ class ListImage(command.Lister): if parsed_args.limit: kwargs['limit'] = parsed_args.limit if parsed_args.marker: - kwargs['marker'] = image_client.find_image(parsed_args.marker).id + kwargs['marker'] = image_client.find_image( + parsed_args.marker, + ignore_missing=False, + ).id if parsed_args.name: kwargs['name'] = parsed_args.name if parsed_args.status: @@ -846,7 +851,7 @@ class ListImage(command.Lister): kwargs['tag'] = parsed_args.tag project_id = None if parsed_args.project: - project_id = common.find_project( + project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, @@ -925,14 +930,17 @@ class ListImageProjects(command.Lister): metavar="<image>", help=_("Image (name or ID)"), ) - common.add_project_domain_option_to_parser(parser) + identity_common.add_project_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): image_client = self.app.client_manager.image columns = ("Image ID", "Member ID", "Status") - image_id = image_client.find_image(parsed_args.image).id + image_id = image_client.find_image( + parsed_args.image, + ignore_missing=False, + ).id data = image_client.members(image=image_id) @@ -963,19 +971,22 @@ class RemoveProjectImage(command.Command): metavar="<project>", help=_("Project to disassociate with image (name or ID)"), ) - common.add_project_domain_option_to_parser(parser) + identity_common.add_project_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): image_client = self.app.client_manager.image identity_client = self.app.client_manager.identity - project_id = common.find_project( - identity_client, parsed_args.project, parsed_args.project_domain + project_id = identity_common.find_project( + identity_client, + parsed_args.project, + parsed_args.project_domain, ).id image = image_client.find_image( - parsed_args.image, ignore_missing=False + parsed_args.image, + ignore_missing=False, ) image_client.remove_member(member=project_id, image=image.id) @@ -1001,7 +1012,10 @@ class SaveImage(command.Command): def take_action(self, parsed_args): image_client = self.app.client_manager.image - image = image_client.find_image(parsed_args.image) + image = image_client.find_image( + parsed_args.image, + ignore_missing=False, + ) output_file = parsed_args.filename if output_file is None: @@ -1176,7 +1190,7 @@ class SetImage(command.Command): metavar="<project>", help=_("Set an alternate project on this image (name or ID)"), ) - common.add_project_domain_option_to_parser(parser) + identity_common.add_project_domain_option_to_parser(parser) for deadopt in self.deadopts: parser.add_argument( "--%s" % deadopt, @@ -1248,7 +1262,7 @@ class SetImage(command.Command): ) project_id = None if parsed_args.project: - project_id = common.find_project( + project_id = identity_common.find_project( identity_client, parsed_args.project, parsed_args.project_domain, @@ -1369,7 +1383,8 @@ class ShowImage(command.ShowOne): image_client = self.app.client_manager.image image = image_client.find_image( - parsed_args.image, ignore_missing=False + parsed_args.image, + ignore_missing=False, ) info = _format_image(image, parsed_args.human_readable) @@ -1413,7 +1428,8 @@ class UnsetImage(command.Command): def take_action(self, parsed_args): image_client = self.app.client_manager.image image = image_client.find_image( - parsed_args.image, ignore_missing=False + parsed_args.image, + ignore_missing=False, ) kwargs = {} @@ -1789,10 +1805,10 @@ class ImportImage(command.ShowOne): 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, + 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, diff --git a/openstackclient/image/v2/metadef_namespaces.py b/openstackclient/image/v2/metadef_namespaces.py index 158fd94e..f09f2002 100644 --- a/openstackclient/image/v2/metadef_namespaces.py +++ b/openstackclient/image/v2/metadef_namespaces.py @@ -15,8 +15,11 @@ """Image V2 Action Implementations""" +import logging + from osc_lib.cli import format_columns from osc_lib.command import command +from osc_lib import exceptions from osc_lib import utils from openstackclient.i18n import _ @@ -25,6 +28,149 @@ _formatters = { 'tags': format_columns.ListColumn, } +LOG = logging.getLogger(__name__) + + +def _format_namespace(namespace): + info = {} + + fields_to_show = [ + 'created_at', + 'description', + 'display_name', + 'namespace', + 'owner', + 'protected', + 'schema', + 'visibility', + ] + + namespace = namespace.to_dict(ignore_none=True, original_names=True) + + # split out the usual key and the properties which are top-level + for key in namespace: + if key in fields_to_show: + info[key] = namespace.get(key) + elif key == "resource_type_associations": + info[key] = [resource_type['name'] + for resource_type in namespace.get(key)] + elif key == 'properties': + info['properties'] = list(namespace.get(key).keys()) + + return info + + +class CreateMetadefNameSpace(command.ShowOne): + _description = _("Create a metadef namespace") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + parser.add_argument( + "namespace", + metavar="<namespace>", + help=_("New metadef namespace name"), + ) + parser.add_argument( + "--display-name", + metavar="<display_name>", + help=_("A user-friendly name for the namespace."), + ) + parser.add_argument( + "--description", + metavar="<description>", + help=_("A description of the namespace"), + ) + visibility_group = parser.add_mutually_exclusive_group() + visibility_group.add_argument( + "--public", + action="store_const", + const="public", + dest="visibility", + help=_("Set namespace visibility 'public'"), + ) + visibility_group.add_argument( + "--private", + action="store_const", + const="private", + dest="visibility", + help=_("Set namespace visibility 'private'"), + ) + protected_group = parser.add_mutually_exclusive_group() + protected_group.add_argument( + "--protected", + action="store_const", + const=True, + dest="is_protected", + help=_("Prevent metadef namespace from being deleted"), + ) + protected_group.add_argument( + "--unprotected", + action="store_const", + const=False, + dest="is_protected", + help=_("Allow metadef namespace to be deleted (default)"), + ) + return parser + + def take_action(self, parsed_args): + image_client = self.app.client_manager.image + filter_keys = [ + 'namespace', + 'display_name', + 'description' + ] + kwargs = {} + + for key in filter_keys: + argument = getattr(parsed_args, key, None) + if argument is not None: + kwargs[key] = argument + + if parsed_args.is_protected is not None: + kwargs['protected'] = parsed_args.is_protected + + if parsed_args.visibility is not None: + kwargs['visibility'] = parsed_args.visibility + + data = image_client.create_metadef_namespace(**kwargs) + + return zip(*sorted(data.items())) + + +class DeleteMetadefNameSpace(command.Command): + _description = _("Delete metadef namespace") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + parser.add_argument( + "namespace_name", + metavar="<namespace_name>", + nargs="+", + help=_("An identifier (a name) for the namespace"), + ) + return parser + + def take_action(self, parsed_args): + image_client = self.app.client_manager.image + + result = 0 + for i in parsed_args.namespace_name: + try: + namespace = image_client.get_metadef_namespace(i) + image_client.delete_metadef_namespace(namespace.id) + except Exception as e: + result += 1 + LOG.error(_("Failed to delete namespace with name or " + "ID '%(namespace)s': %(e)s"), + {'namespace': i, 'e': e} + ) + + if result > 0: + total = len(parsed_args.namespace_name) + msg = (_("%(result)s of %(total)s namespace failed " + "to delete.") % {'result': result, 'total': total}) + raise exceptions.CommandError(msg) + class ListMetadefNameSpaces(command.Lister): _description = _("List metadef namespaces") @@ -63,3 +209,104 @@ class ListMetadefNameSpaces(command.Lister): formatters=_formatters, ) for s in data) ) + + +class SetMetadefNameSpace(command.Command): + _description = _("Set metadef namespace properties") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + parser.add_argument( + "namespace", + metavar="<namespace>", + help=_("Namespace (name) for the namespace"), + ) + parser.add_argument( + "--display-name", + metavar="<display_name>", + help=_("Set a user-friendly name for the namespace."), + ) + parser.add_argument( + "--description", + metavar="<description>", + help=_("Set the description of the namespace"), + ) + visibility_group = parser.add_mutually_exclusive_group() + visibility_group.add_argument( + "--public", + action="store_const", + const="public", + dest="visibility", + help=_("Set namespace visibility 'public'"), + ) + visibility_group.add_argument( + "--private", + action="store_const", + const="private", + dest="visibility", + help=_("Set namespace visibility 'private'"), + ) + protected_group = parser.add_mutually_exclusive_group() + protected_group.add_argument( + "--protected", + action="store_const", + const=True, + dest="is_protected", + help=_("Prevent metadef namespace from being deleted"), + ) + protected_group.add_argument( + "--unprotected", + action="store_const", + const=False, + dest="is_protected", + help=_("Allow metadef namespace to be deleted (default)"), + ) + return parser + + def take_action(self, parsed_args): + image_client = self.app.client_manager.image + + namespace = parsed_args.namespace + + filter_keys = [ + 'namespace', + 'display_name', + 'description' + ] + kwargs = {} + + for key in filter_keys: + argument = getattr(parsed_args, key, None) + if argument is not None: + kwargs[key] = argument + + if parsed_args.is_protected is not None: + kwargs['protected'] = parsed_args.is_protected + + if parsed_args.visibility is not None: + kwargs['visibility'] = parsed_args.visibility + + image_client.update_metadef_namespace(namespace, **kwargs) + + +class ShowMetadefNameSpace(command.ShowOne): + _description = _("Show a metadef namespace") + + def get_parser(self, prog_name): + parser = super().get_parser(prog_name) + parser.add_argument( + "namespace_name", + metavar="<namespace_name>", + help=_("Namespace (name) for the namespace"), + ) + return parser + + def take_action(self, parsed_args): + image_client = self.app.client_manager.image + + namespace_name = parsed_args.namespace_name + + data = image_client.get_metadef_namespace(namespace_name) + info = _format_namespace(data) + + return zip(*sorted(info.items())) |
