Glance image set Resolve Fracturing

Currently `image set` uses the new api, where other parts of osc the old
api is used. This deprecates the v2 api in favour of the v1 to maintain
the same commands across osc. However the functionality now remains
there as people could now be using this functionality.

This also adds the --unprotected argument, as in the previous version if
--protected was not supplied it would just make the argument
--unprotected without the users explicit consent.

The patch also fixes the documentation for image set as it was outdated.

Change-Id: I990d20332c80165102badef7ac94ddbeb7824950
Closes-Bug: 1498092
This commit is contained in:
NiallBunting 2015-09-22 09:59:30 +00:00 committed by Steve Martinelli
parent 2616fdb089
commit 8faabb3bba
3 changed files with 119 additions and 9 deletions

View File

@ -193,7 +193,7 @@ Save an image locally
image set image set
--------- ---------
*Only supported for Image v1* *Image v1, v2*
Set image properties Set image properties
@ -252,6 +252,8 @@ Set image properties
Size of image data (in bytes) Size of image data (in bytes)
*Image version 1 only.*
.. option:: --protected .. option:: --protected
Prevent image from being deleted Prevent image from being deleted
@ -272,38 +274,94 @@ Set image properties
Upload image to this store Upload image to this store
*Image version 1 only.*
.. option:: --location <image-url> .. option:: --location <image-url>
Download image from an existing URL Download image from an existing URL
*Image version 1 only.*
.. option:: --copy-from <image-url> .. option:: --copy-from <image-url>
Copy image from the data store (similar to --location) Copy image from the data store (similar to --location)
*Image version 1 only.*
.. option:: --file <file> .. option:: --file <file>
Upload image from local file Upload image from local file
*Image version 1 only.*
.. option:: --volume <volume> .. option:: --volume <volume>
Update image with a volume Update image with a volume
*Image version 1 only.*
.. option:: --force .. option:: --force
Force image update if volume is in use (only meaningful with --volume) Force image update if volume is in use (only meaningful with --volume)
*Image version 1 only.*
.. option:: --checksum <checksum> .. option:: --checksum <checksum>
Image hash used for verification Image hash used for verification
*Image version 1 only.*
.. option:: --stdin .. option:: --stdin
Allow to read image data from standard input Allow to read image data from standard input
*Image version 1 only.*
.. option:: --property <key=value> .. option:: --property <key=value>
Set a property on this image (repeat for multiple values) Set a property on this image (repeat for multiple values)
*Image version 1 only.*
.. option:: --architecture <architecture>
Operating system Architecture
.. versionadded:: 2
.. option:: --ramdisk-id <ramdisk-id>
ID of image stored in Glance that should be used as
the ramdisk when booting an AMI-style image
.. versionadded:: 2
.. option:: --os-distro <os-distro>
Common name of operating system distribution
.. versionadded:: 2
.. option:: --os-version <os-version>
Operating system version as specified by the distributor
.. versionadded:: 2
.. option:: --kernel-id <kernel-id>
ID of image in Glance that should be used as the
kernel when booting an AMI-style image
.. versionadded:: 2
.. option:: --instance-uuid <instance_uuid>
ID of instance used to create this image
.. versionadded:: 2
.. describe:: <image> .. describe:: <image>
Image to modify (name or ID) Image to modify (name or ID)

View File

@ -25,6 +25,7 @@ from cliff import show
from glanceclient.common import utils as gc_utils from glanceclient.common import utils as gc_utils
from openstackclient.api import utils as api_utils from openstackclient.api import utils as api_utils
from openstackclient.common import exceptions
from openstackclient.common import parseractions from openstackclient.common import parseractions
from openstackclient.common import utils from openstackclient.common import utils
from openstackclient.identity import common from openstackclient.identity import common
@ -336,9 +337,22 @@ class SetImage(show.ShowOne):
"""Set image properties""" """Set image properties"""
log = logging.getLogger(__name__ + ".SetImage") log = logging.getLogger(__name__ + ".SetImage")
deadopts = ('size', 'store', 'location', 'copy-from', 'checksum')
def get_parser(self, prog_name): def get_parser(self, prog_name):
parser = super(SetImage, self).get_parser(prog_name) parser = super(SetImage, self).get_parser(prog_name)
# TODO(bunting): There are additional arguments that v1 supported
# --size - does not exist in v2
# --store - does not exist in v2
# --location - maybe location add?
# --copy-from - does not exist in v2
# --file - should be able to upload file
# --volume - needs adding
# --force - needs adding
# --checksum - maybe could be done client side
# --stdin - could be implemented
# --property - needs adding
# --tags - needs adding
parser.add_argument( parser.add_argument(
"image", "image",
metavar="<image>", metavar="<image>",
@ -354,12 +368,28 @@ class SetImage(show.ShowOne):
metavar="<architecture>", metavar="<architecture>",
help="Operating system Architecture" help="Operating system Architecture"
) )
parser.add_argument( protected_group = parser.add_mutually_exclusive_group()
protected_group.add_argument(
"--protected", "--protected",
dest="protected",
action="store_true", action="store_true",
help="Prevent image from being deleted" help="Prevent image from being deleted"
) )
protected_group.add_argument(
"--unprotected",
action="store_true",
help="Allow image to be deleted (default)"
)
public_group = parser.add_mutually_exclusive_group()
public_group.add_argument(
"--public",
action="store_true",
help="Image is accessible to the public",
)
public_group.add_argument(
"--private",
action="store_true",
help="Image is inaccessible to the public (default)",
)
parser.add_argument( parser.add_argument(
"--instance-uuid", "--instance-uuid",
metavar="<instance_uuid>", metavar="<instance_uuid>",
@ -372,12 +402,11 @@ class SetImage(show.ShowOne):
help="Minimum disk size needed to boot image, in gigabytes" help="Minimum disk size needed to boot image, in gigabytes"
) )
visibility_choices = ["public", "private"] visibility_choices = ["public", "private"]
parser.add_argument( public_group.add_argument(
"--visibility", "--visibility",
metavar="<visibility>", metavar="<visibility>",
choices=visibility_choices, choices=visibility_choices,
help="Scope of image accessibility. Valid values: %s" help=argparse.SUPPRESS
% visibility_choices
) )
help_msg = ("ID of image in Glance that should be used as the kernel" help_msg = ("ID of image in Glance that should be used as the kernel"
" when booting an AMI-style image") " when booting an AMI-style image")
@ -432,12 +461,25 @@ class SetImage(show.ShowOne):
choices=container_choices, choices=container_choices,
help=help_msg help=help_msg
) )
for deadopt in self.deadopts:
parser.add_argument(
"--%s" % deadopt,
metavar="<%s>" % deadopt,
dest=deadopt.replace('-', '_'),
help=argparse.SUPPRESS
)
return parser return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
self.log.debug("take_action(%s)", parsed_args) self.log.debug("take_action(%s)", parsed_args)
image_client = self.app.client_manager.image image_client = self.app.client_manager.image
for deadopt in self.deadopts:
if getattr(parsed_args, deadopt.replace('-', '_'), None):
raise exceptions.CommandError(
"ERROR: --%s was given, which is an Image v1 option"
" that is no longer supported in Image v2" % deadopt)
kwargs = {} kwargs = {}
copy_attrs = ('architecture', 'container_format', 'disk_format', copy_attrs = ('architecture', 'container_format', 'disk_format',
'file', 'kernel_id', 'locations', 'name', 'file', 'kernel_id', 'locations', 'name',
@ -451,10 +493,21 @@ class SetImage(show.ShowOne):
# Only include a value in kwargs for attributes that are # Only include a value in kwargs for attributes that are
# actually present on the command line # actually present on the command line
kwargs[attr] = val kwargs[attr] = val
# Handle exclusive booleans with care
# Avoid including attributes in kwargs if an option is not
# present on the command line. These exclusive booleans are not
# a single value for the pair of options because the default must be
# to do nothing when no options are present as opposed to always
# setting a default.
if parsed_args.protected: if parsed_args.protected:
kwargs['protected'] = True kwargs['protected'] = True
else: if parsed_args.unprotected:
kwargs['protected'] = False kwargs['protected'] = False
if parsed_args.public:
kwargs['visibility'] = 'public'
if parsed_args.private:
kwargs['visibility'] = 'private'
if not kwargs: if not kwargs:
self.log.warning("No arguments specified") self.log.warning("No arguments specified")

View File

@ -527,8 +527,7 @@ class TestImageSet(TestImage):
'name': 'new-name', 'name': 'new-name',
'owner': 'new-owner', 'owner': 'new-owner',
'min_disk': 2, 'min_disk': 2,
'min_ram': 4, 'min_ram': 4
'protected': False
} }
# ImageManager.update(image, **kwargs) # ImageManager.update(image, **kwargs)
self.images_mock.update.assert_called_with( self.images_mock.update.assert_called_with(