summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStuart McLaren <stuart.mclaren@hp.com>2015-12-07 16:46:54 +0000
committerStuart McLaren <stuart.mclaren@hp.com>2016-02-24 18:31:38 +0000
commit5b9f21b38b59322d6c9423aa4f5b028e72dd01f6 (patch)
treed51039198361e26592bd6ee5171f9f013d0fee00
parent44d0b02c67ce7926f40377d9367a0f61124ed26d (diff)
downloadpython-glanceclient-5b9f21b38b59322d6c9423aa4f5b028e72dd01f6.tar.gz
Handle 403 forbidden on download
A download of a deactivated image may result in a 403. The cli should catch this error rather than stack trace. We also catch other unexpected http responses. Change-Id: If33fbc3a56cdb02b3ab32a6479a67fff20b4b1a9 Closes-bug: 1523612
-rw-r--r--glanceclient/common/utils.py2
-rw-r--r--glanceclient/tests/unit/v2/test_images.py9
-rw-r--r--glanceclient/tests/unit/v2/test_shell_v2.py30
-rw-r--r--glanceclient/v2/shell.py7
4 files changed, 46 insertions, 2 deletions
diff --git a/glanceclient/common/utils.py b/glanceclient/common/utils.py
index 88144ef..0534d35 100644
--- a/glanceclient/common/utils.py
+++ b/glanceclient/common/utils.py
@@ -283,7 +283,7 @@ def import_versioned_module(version, submodule=None):
def exit(msg='', exit_code=1):
if msg:
- print(encodeutils.safe_decode(msg), file=sys.stderr)
+ print_err(msg)
sys.exit(exit_code)
diff --git a/glanceclient/tests/unit/v2/test_images.py b/glanceclient/tests/unit/v2/test_images.py
index 1573228..049528b 100644
--- a/glanceclient/tests/unit/v2/test_images.py
+++ b/glanceclient/tests/unit/v2/test_images.py
@@ -872,6 +872,15 @@ class TestController(testtools.TestCase):
body = self.controller.data('image_id')
self.assertEqual(None, body)
+ def test_download_forbidden(self):
+ self.controller.http_client.get = mock.Mock(
+ side_effect=exc.HTTPForbidden())
+ try:
+ self.controller.data('image_id')
+ self.fail('No forbidden exception raised.')
+ except exc.HTTPForbidden:
+ pass
+
def test_update_replace_prop(self):
image_id = '3a4560a1-e585-443e-9b39-553b46ec92d1'
params = {'name': 'pong'}
diff --git a/glanceclient/tests/unit/v2/test_shell_v2.py b/glanceclient/tests/unit/v2/test_shell_v2.py
index cdd0ba2..b473019 100644
--- a/glanceclient/tests/unit/v2/test_shell_v2.py
+++ b/glanceclient/tests/unit/v2/test_shell_v2.py
@@ -652,6 +652,36 @@ class ShellV2Test(testtools.TestCase):
self.assert_exits_with_msg(func=test_shell.do_image_delete,
func_args=args)
+ @mock.patch.object(utils, 'print_err')
+ def test_do_image_download_with_forbidden_id(self, mocked_print_err):
+ args = self._make_args({'id': 'IMG-01', 'file': None,
+ 'progress': False})
+ with mock.patch.object(self.gc.images, 'data') as mocked_data:
+ mocked_data.side_effect = exc.HTTPForbidden
+ try:
+ test_shell.do_image_download(self.gc, args)
+ self.fail('Exit not called')
+ except SystemExit:
+ pass
+
+ self.assertEqual(1, mocked_data.call_count)
+ self.assertEqual(1, mocked_print_err.call_count)
+
+ @mock.patch.object(utils, 'print_err')
+ def test_do_image_download_with_500(self, mocked_print_err):
+ args = self._make_args({'id': 'IMG-01', 'file': None,
+ 'progress': False})
+ with mock.patch.object(self.gc.images, 'data') as mocked_data:
+ mocked_data.side_effect = exc.HTTPInternalServerError
+ try:
+ test_shell.do_image_download(self.gc, args)
+ self.fail('Exit not called')
+ except SystemExit:
+ pass
+
+ self.assertEqual(1, mocked_data.call_count)
+ self.assertEqual(1, mocked_print_err.call_count)
+
def test_do_member_list(self):
args = self._make_args({'image_id': 'IMG-01'})
with mock.patch.object(self.gc.image_members, 'list') as mocked_list:
diff --git a/glanceclient/v2/shell.py b/glanceclient/v2/shell.py
index 99ca397..f9b9318 100644
--- a/glanceclient/v2/shell.py
+++ b/glanceclient/v2/shell.py
@@ -275,7 +275,12 @@ def do_explain(gc, args):
help=_('Show download progress bar.'))
def do_image_download(gc, args):
"""Download a specific image."""
- body = gc.images.data(args.id)
+ try:
+ body = gc.images.data(args.id)
+ except (exc.HTTPForbidden, exc.HTTPException) as e:
+ msg = "Unable to download image '%s'. (%s)" % (args.id, e)
+ utils.exit(msg)
+
if body is None:
msg = ('Image %s has no data.' % args.id)
utils.exit(msg)