diff --git a/doc/source/command-objects/image.rst b/doc/source/command-objects/image.rst index d4b9916221..6a4782ea5e 100644 --- a/doc/source/command-objects/image.rst +++ b/doc/source/command-objects/image.rst @@ -243,6 +243,7 @@ Set image properties [--os-distro <os-distro>] [--os-version <os-version>] [--ramdisk-id <ramdisk-id>] + [--activate|--deactivate] <image> .. option:: --name <name> @@ -387,6 +388,18 @@ Set image properties .. versionadded:: 2 +.. option:: --activate + + Activate the image. + + .. versionadded:: 2 + +.. option:: --deactivate + + Deactivate the image. + + .. versionadded:: 2 + .. describe:: <image> Image to modify (name or ID) diff --git a/openstackclient/image/v2/image.py b/openstackclient/image/v2/image.py index a3c1a99d17..1fcb92d9a5 100644 --- a/openstackclient/image/v2/image.py +++ b/openstackclient/image/v2/image.py @@ -693,6 +693,17 @@ class SetImage(command.Command): metavar="<ramdisk-id>", help="ID of ramdisk image used to boot this disk image", ) + deactivate_group = parser.add_mutually_exclusive_group() + deactivate_group.add_argument( + "--deactivate", + action="store_true", + help="Deactivate the image", + ) + deactivate_group.add_argument( + "--activate", + action="store_true", + help="Activate the image", + ) for deadopt in self.deadopts: parser.add_argument( "--%s" % deadopt, @@ -745,18 +756,35 @@ class SetImage(command.Command): if parsed_args.private: kwargs['visibility'] = 'private' - if not kwargs: + # Checks if anything that requires getting the image + if not (kwargs or parsed_args.deactivate or parsed_args.activate): self.log.warning("No arguments specified") return {}, {} image = utils.find_resource( image_client.images, parsed_args.image) + if parsed_args.deactivate: + image_client.images.deactivate(image.id) + activation_status = "deactivated" + if parsed_args.activate: + image_client.images.reactivate(image.id) + activation_status = "activated" + + # Check if need to do the actual update + if not kwargs: + return {}, {} + if parsed_args.tags: # Tags should be extended, but duplicates removed kwargs['tags'] = list(set(image.tags).union(set(parsed_args.tags))) - image = image_client.images.update(image.id, **kwargs) + try: + image = image_client.images.update(image.id, **kwargs) + except Exception as e: + if activation_status is not None: + print("Image %s was %s." % (image.id, activation_status)) + raise e class ShowImage(show.ShowOne): diff --git a/openstackclient/tests/image/v2/test_image.py b/openstackclient/tests/image/v2/test_image.py index be73c4ca9c..71e1a77b0a 100644 --- a/openstackclient/tests/image/v2/test_image.py +++ b/openstackclient/tests/image/v2/test_image.py @@ -838,6 +838,64 @@ class TestImageSet(TestImage): **kwargs ) + def test_image_set_activate(self): + arglist = [ + '--tag', 'test-tag', + '--activate', + image_fakes.image_name, + ] + verifylist = [ + ('tags', ['test-tag']), + ('image', image_fakes.image_name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # DisplayCommandBase.take_action() returns two tuples + self.cmd.take_action(parsed_args) + + kwargs = { + 'tags': ['test-tag'], + } + + self.images_mock.reactivate.assert_called_with( + image_fakes.image_id, + ) + + # ImageManager.update(image, **kwargs) + self.images_mock.update.assert_called_with( + image_fakes.image_id, + **kwargs + ) + + def test_image_set_deactivate(self): + arglist = [ + '--tag', 'test-tag', + '--deactivate', + image_fakes.image_name, + ] + verifylist = [ + ('tags', ['test-tag']), + ('image', image_fakes.image_name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # DisplayCommandBase.take_action() returns two tuples + self.cmd.take_action(parsed_args) + + kwargs = { + 'tags': ['test-tag'], + } + + self.images_mock.deactivate.assert_called_with( + image_fakes.image_id, + ) + + # ImageManager.update(image, **kwargs) + self.images_mock.update.assert_called_with( + image_fakes.image_id, + **kwargs + ) + def test_image_set_tag_merge(self): old_image = copy.copy(image_fakes.IMAGE) old_image['tags'] = ['old1', 'new2']