image: Migrate 'create image' volume calls to SDK
Change-Id: Ie57a5c17a6df5a333abd6b11e28b65833740e102 Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
		| @@ -17,14 +17,15 @@ | ||||
|  | ||||
| import argparse | ||||
| from base64 import b64encode | ||||
| import copy | ||||
| import logging | ||||
| import os | ||||
| import sys | ||||
| import typing as ty | ||||
|  | ||||
| from cinderclient import api_versions | ||||
| from openstack import exceptions as sdk_exceptions | ||||
| from openstack.image import image_signer | ||||
| from openstack import utils as sdk_utils | ||||
| from osc_lib.api import utils as api_utils | ||||
| from osc_lib.cli import format_columns | ||||
| from osc_lib.cli import parseractions | ||||
| @@ -576,7 +577,7 @@ class CreateImage(command.ShowOne): | ||||
|         return _format_image(image) | ||||
|  | ||||
|     def _take_action_volume(self, parsed_args): | ||||
|         volume_client = self.app.client_manager.volume | ||||
|         volume_client = self.app.client_manager.sdk_connection.volume | ||||
|  | ||||
|         unsupported_opts = { | ||||
|             # 'name',  # 'name' is a positional argument and will always exist | ||||
| @@ -607,15 +608,14 @@ class CreateImage(command.ShowOne): | ||||
|                 # version | ||||
|                 LOG.warning(msg % opt_name) | ||||
|  | ||||
|         source_volume = utils.find_resource( | ||||
|             volume_client.volumes, | ||||
|             parsed_args.volume, | ||||
|         source_volume = volume_client.find_volume( | ||||
|             parsed_args.volume, ignore_missing=False | ||||
|         ) | ||||
|         kwargs: dict[str, ty.Any] = { | ||||
|             'visibility': None, | ||||
|             'protected': None, | ||||
|         } | ||||
|         if volume_client.api_version < api_versions.APIVersion('3.1'): | ||||
|         if not sdk_utils.supports_microversion(volume_client, '3.1'): | ||||
|             if parsed_args.visibility or parsed_args.is_protected is not None: | ||||
|                 msg = _( | ||||
|                     '--os-volume-api-version 3.1 or greater is required ' | ||||
| @@ -627,15 +627,15 @@ class CreateImage(command.ShowOne): | ||||
|             kwargs['visibility'] = parsed_args.visibility or 'private' | ||||
|             kwargs['protected'] = parsed_args.is_protected or False | ||||
|  | ||||
|         response, body = volume_client.volumes.upload_to_image( | ||||
|         response = volume_client.upload_volume_to_image( | ||||
|             source_volume.id, | ||||
|             parsed_args.force, | ||||
|             parsed_args.name, | ||||
|             parsed_args.container_format, | ||||
|             parsed_args.disk_format, | ||||
|             force=parsed_args.force, | ||||
|             disk_format=parsed_args.disk_format, | ||||
|             container_format=parsed_args.container_format, | ||||
|             **kwargs, | ||||
|         ) | ||||
|         info = body['os-volume_upload_image'] | ||||
|         info = copy.deepcopy(response) | ||||
|         try: | ||||
|             info['volume_type'] = info['volume_type']['name'] | ||||
|         except TypeError: | ||||
|   | ||||
| @@ -17,8 +17,9 @@ import io | ||||
| import tempfile | ||||
| from unittest import mock | ||||
|  | ||||
| from cinderclient import api_versions | ||||
| from openstack.block_storage.v2 import volume as _volume | ||||
| from openstack import exceptions as sdk_exceptions | ||||
| from openstack.test import fakes as sdk_fakes | ||||
| from osc_lib.cli import format_columns | ||||
| from osc_lib import exceptions | ||||
|  | ||||
| @@ -37,12 +38,6 @@ class TestImage(image_fakes.TestImagev2, volume_fakes.TestVolume): | ||||
|         self.project_mock.reset_mock() | ||||
|         self.domain_mock = self.identity_client.domains | ||||
|         self.domain_mock.reset_mock() | ||||
|         self.volumes_mock = self.volume_client.volumes | ||||
|         fake_body = { | ||||
|             'os-volume_upload_image': {'volume_type': {'name': 'fake_type'}} | ||||
|         } | ||||
|         self.volumes_mock.upload_to_image.return_value = (200, fake_body) | ||||
|         self.volumes_mock.reset_mock() | ||||
|  | ||||
|  | ||||
| class TestImageCreate(TestImage): | ||||
| @@ -312,7 +307,6 @@ class TestImageCreate(TestImage): | ||||
|  | ||||
|         columns, data = self.cmd.take_action(parsed_args) | ||||
|  | ||||
|         # ImageManager.create(name=, **) | ||||
|         self.image_client.create_image.assert_called_with( | ||||
|             name=self.new_image.name, | ||||
|             allow_duplicates=True, | ||||
| @@ -322,20 +316,19 @@ class TestImageCreate(TestImage): | ||||
|         ) | ||||
|         self.image_client.get_image.assert_called_once_with(self.new_image) | ||||
|  | ||||
|     @mock.patch('osc_lib.utils.find_resource') | ||||
|     @mock.patch('openstackclient.image.v2.image.get_data_from_stdin') | ||||
|     def test_image_create_from_volume(self, mock_get_data_f, mock_get_vol): | ||||
|         fake_vol_id = 'fake-volume-id' | ||||
|     def test_image_create_from_volume(self, mock_get_data_f): | ||||
|         mock_get_data_f.return_value = None | ||||
|  | ||||
|         class FakeVolume: | ||||
|             id = fake_vol_id | ||||
|  | ||||
|         mock_get_vol.return_value = FakeVolume() | ||||
|         volume = sdk_fakes.generate_fake_resource(_volume.Volume) | ||||
|         self.volume_sdk_client.find_volume.return_value = volume | ||||
|         self.volume_sdk_client.upload_volume_to_image.return_value = { | ||||
|             'volume_type': {'name': 'fake_type'} | ||||
|         } | ||||
|  | ||||
|         arglist = [ | ||||
|             '--volume', | ||||
|             fake_vol_id, | ||||
|             volume.id, | ||||
|             self.new_image.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
| @@ -345,53 +338,60 @@ class TestImageCreate(TestImage): | ||||
|  | ||||
|         columns, data = self.cmd.take_action(parsed_args) | ||||
|  | ||||
|         self.volumes_mock.upload_to_image.assert_called_with( | ||||
|             fake_vol_id, | ||||
|             False, | ||||
|         self.volume_sdk_client.upload_volume_to_image.assert_called_once_with( | ||||
|             volume.id, | ||||
|             self.new_image.name, | ||||
|             'bare', | ||||
|             'raw', | ||||
|             force=False, | ||||
|             disk_format='raw', | ||||
|             container_format='bare', | ||||
|             visibility=None, | ||||
|             protected=None, | ||||
|         ) | ||||
|  | ||||
|     @mock.patch('osc_lib.utils.find_resource') | ||||
|     @mock.patch('openstackclient.image.v2.image.get_data_from_stdin') | ||||
|     def test_image_create_from_volume_fail( | ||||
|         self, mock_get_data_f, mock_get_vol | ||||
|     ): | ||||
|         fake_vol_id = 'fake-volume-id' | ||||
|     def test_image_create_from_volume_pre_v31(self, mock_get_data_f): | ||||
|         mock_get_data_f.return_value = None | ||||
|  | ||||
|         class FakeVolume: | ||||
|             id = fake_vol_id | ||||
|         volume = sdk_fakes.generate_fake_resource(_volume.Volume) | ||||
|         self.volume_sdk_client.find_volume.return_value = volume | ||||
|         self.volume_sdk_client.upload_volume_to_image.return_value = { | ||||
|             'volume_type': {'name': 'fake_type'} | ||||
|         } | ||||
|  | ||||
|         mock_get_vol.return_value = FakeVolume() | ||||
|  | ||||
|         arglist = ['--volume', fake_vol_id, self.new_image.name, '--public'] | ||||
|         arglist = [ | ||||
|             '--volume', | ||||
|             volume.id, | ||||
|             self.new_image.name, | ||||
|             '--public', | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('name', self.new_image.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         self.assertRaises( | ||||
|         exc = self.assertRaises( | ||||
|             exceptions.CommandError, self.cmd.take_action, parsed_args | ||||
|         ) | ||||
|         self.assertIn('--os-volume-api-version 3.1 or greater ', str(exc)) | ||||
|  | ||||
|     @mock.patch('osc_lib.utils.find_resource') | ||||
|     @mock.patch('openstackclient.image.v2.image.get_data_from_stdin') | ||||
|     def test_image_create_from_volume_v31(self, mock_get_data_f, mock_get_vol): | ||||
|         self.volume_client.api_version = api_versions.APIVersion('3.1') | ||||
|     def test_image_create_from_volume_v31(self, mock_get_data_f): | ||||
|         self.set_volume_api_version('3.1') | ||||
|  | ||||
|         fake_vol_id = 'fake-volume-id' | ||||
|         mock_get_data_f.return_value = None | ||||
|  | ||||
|         class FakeVolume: | ||||
|             id = fake_vol_id | ||||
|         volume = sdk_fakes.generate_fake_resource(_volume.Volume) | ||||
|         self.volume_sdk_client.find_volume.return_value = volume | ||||
|         self.volume_sdk_client.upload_volume_to_image.return_value = { | ||||
|             'volume_type': {'name': 'fake_type'} | ||||
|         } | ||||
|  | ||||
|         mock_get_vol.return_value = FakeVolume() | ||||
|  | ||||
|         arglist = ['--volume', fake_vol_id, self.new_image.name, '--public'] | ||||
|         arglist = [ | ||||
|             '--volume', | ||||
|             volume.id, | ||||
|             self.new_image.name, | ||||
|             '--public', | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('name', self.new_image.name), | ||||
|         ] | ||||
| @@ -399,12 +399,12 @@ class TestImageCreate(TestImage): | ||||
|  | ||||
|         columns, data = self.cmd.take_action(parsed_args) | ||||
|  | ||||
|         self.volumes_mock.upload_to_image.assert_called_with( | ||||
|             fake_vol_id, | ||||
|             False, | ||||
|         self.volume_sdk_client.upload_volume_to_image.assert_called_once_with( | ||||
|             volume.id, | ||||
|             self.new_image.name, | ||||
|             'bare', | ||||
|             'raw', | ||||
|             force=False, | ||||
|             disk_format='raw', | ||||
|             container_format='bare', | ||||
|             visibility='public', | ||||
|             protected=False, | ||||
|         ) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Stephen Finucane
					Stephen Finucane