summaryrefslogtreecommitdiff
path: root/openstackclient/image
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient/image')
-rw-r--r--openstackclient/image/v2/image.py66
-rw-r--r--openstackclient/image/v2/metadef_namespaces.py247
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()))