Add support for web-download import method

This change adds support for 'web-download' import method
to 'image-import' and 'create-image-via-import' call.
To use this 'web-download' import method, user needs to pass
--uri option 'a valid uri to external image to import in glance'
to 'image-import' and 'create-image-via-imaport' calls.

Co-authored-by: Pranali Deore <pdeore@redhat.com>
Co-authored-by: Erno Kuvaja <jokke@usr.fi>

Change-Id: I0e1d18844f64723608288de473e97710798eb602
This commit is contained in:
PranaliD 2018-03-12 05:38:34 -04:00 committed by Erno Kuvaja
parent 558580febf
commit aedabec9e4
5 changed files with 83 additions and 6 deletions

View File

@ -106,6 +106,10 @@ class BaseController(testtools.TestCase):
resp = self.controller.deassociate(*args)
self._assertRequestId(resp)
def image_import(self, *args):
resp = self.controller.image_import(*args)
self._assertRequestId(resp)
class BaseResourceTypeController(BaseController):
def __init__(self, api, schema_api, controller_class):

View File

@ -215,6 +215,9 @@ data_fixtures = {
'/v2/images/87b634c1-f893-33c9-28a9-e5673c99239a/actions/deactivate': {
'POST': ({}, None)
},
'/v2/images/606b0e88-7c5a-4d54-b5bb-046105d4de6f/import': {
'POST': ({}, None)
},
'/v2/images?limit=%d&visibility=public' % images.DEFAULT_PAGE_SIZE: {
'GET': (
{},
@ -867,6 +870,16 @@ class TestController(testtools.TestCase):
body = ''.join([b for b in body])
self.assertEqual('CCC', body)
def test_image_import(self):
uri = 'http://example.com/image.qcow'
data = [('method', {'name': 'web-download',
'uri': uri})]
image_id = '606b0e88-7c5a-4d54-b5bb-046105d4de6f'
self.controller.image_import(image_id, 'web-download', uri)
expect = [('POST', '/v2/images/%s/import' % image_id, {},
data)]
self.assertEqual(expect, self.api.calls)
def test_download_no_data(self):
resp = utils.FakeResponse(headers={}, status_code=204)
self.controller.controller.http_client.get = mock.Mock(

View File

@ -447,6 +447,33 @@ class ShellV2Test(testtools.TestCase):
utils.print_dict.assert_called_once_with({
'id': 'pass', 'name': 'IMG-01', 'myprop': 'myval'})
def test_do_image_create_via_import_with_web_download(self):
temp_args = {'name': 'IMG-01',
'disk_format': 'vhd',
'container_format': 'bare',
'uri': 'http://example.com/image.qcow',
'import_method': 'web-download',
'progress': False}
args = self._make_args(temp_args)
with mock.patch.object(self.gc.images, 'create') as mocked_create:
with mock.patch.object(self.gc.images, 'get') as mocked_get:
ignore_fields = ['self', 'access', 'schema']
expect_image = dict([(field, field) for field in
ignore_fields])
expect_image['id'] = 'pass'
expect_image['name'] = 'IMG-01'
expect_image['disk_format'] = 'vhd'
expect_image['container_format'] = 'bare'
mocked_create.return_value = expect_image
mocked_get.return_value = expect_image
test_shell.do_image_create_via_import(self.gc, args)
mocked_create.assert_called_once_with(**temp_args)
mocked_get.assert_called_with('pass')
utils.print_dict.assert_called_with({
'id': 'pass', 'name': 'IMG-01', 'disk_format': 'vhd',
'container_format': 'bare'})
def test_do_image_update_no_user_props(self):
args = self._make_args({'id': 'pass', 'name': 'IMG-01',
'disk_format': 'vhd',
@ -577,6 +604,17 @@ class ShellV2Test(testtools.TestCase):
test_shell.do_image_upload(self.gc, args)
mocked_upload.assert_called_once_with('IMG-01', 'testfile', 1024)
def test_image_import(self):
args = self._make_args(
{'id': 'IMG-01', 'uri': 'http://example.com/image.qcow',
'import_method': 'web-download', 'from_create': True})
with mock.patch.object(self.gc.images, 'image_import') as mock_import:
mock_import.return_value = None
test_shell.do_image_import(self.gc, args)
mock_import.assert_called_once_with(
'IMG-01', 'web-download', 'http://example.com/image.qcow')
def test_image_download(self):
args = self._make_args(
{'id': 'IMG-01', 'file': 'test', 'progress': True})

View File

@ -254,10 +254,16 @@ class Controller(object):
return body, resp
@utils.add_req_id_to_object()
def image_import(self, image_id, method='glance-direct'):
def image_import(self, image_id, method='glance-direct', uri=None):
"""Import Image via method."""
url = '/v2/images/%s/import' % image_id
data = {'method': {'name': method}}
if uri:
if method == 'web-download':
data['method']['uri'] = uri
else:
raise exc.HTTPBadRequest('URI is only supported with method: '
'"web-download"')
resp, body = self.http_client.post(url, data=data)
return body, resp

View File

@ -105,6 +105,8 @@ def do_image_create(gc, args):
@utils.arg('--import-method', metavar='<METHOD>', default='glance-direct',
help=_('Import method used for Image Import workflow. '
'Valid values can be retrieved with import-info command.'))
@utils.arg('--uri', metavar='<IMAGE_URL>', default=None,
help=_('URI to download the external image.'))
@utils.on_data_require_fields(DATA_FIELDS)
def do_image_create_via_import(gc, args):
"""EXPERIMENTAL: Create a new image via image import."""
@ -129,15 +131,22 @@ def do_image_create_via_import(gc, args):
'glance-direct' not in import_methods.get('value')):
utils.exit("No suitable import method available for direct upload, "
"please use image-create instead.")
if args.import_method == 'web-download' and not args.uri:
utils.exit("URI is required for web-download import method. "
"Please use '--uri <uri>'.")
if args.uri and args.import_method != 'web-download':
utils.exit("Import method should be 'web-download' if URI is "
"provided.")
image = gc.images.create(**fields)
try:
args.id = image['id']
if utils.get_data_file(args) is not None:
args.id = image['id']
args.size = None
do_image_stage(gc, args)
args.from_create = True
do_image_import(gc, args)
image = gc.images.get(args.id)
args.from_create = True
do_image_import(gc, args)
image = gc.images.get(args.id)
finally:
utils.print_image(image)
@ -418,12 +427,19 @@ def do_image_stage(gc, args):
'Valid values can be retrieved with import-info command '
'and the default "glance-direct" is used with '
'"image-stage".'))
@utils.arg('--uri', metavar='<IMAGE_URL>', default=None,
help=_('URI to download the external image.'))
@utils.arg('id', metavar='<IMAGE_ID>',
help=_('ID of image to import.'))
def do_image_import(gc, args):
"""Initiate the image import taskflow."""
try:
gc.images.image_import(args.id, args.import_method)
if args.import_method == 'web-download' and not args.uri:
utils.exit("Provide URI for web-download import method.")
if args.uri and args.import_method != 'web-download':
utils.exit("Import method should be 'web-download' if URI is "
"provided.")
gc.images.image_import(args.id, args.import_method, args.uri)
except exc.HTTPNotFound:
utils.exit('Target Glance does not support Image Import workflow')
else: