Merge "Check if v2 is available and fallback"

This commit is contained in:
Jenkins
2015-09-08 20:45:52 +00:00
committed by Gerrit Code Review
4 changed files with 70 additions and 21 deletions

View File

@@ -91,7 +91,10 @@ class _BaseHTTPClient(object):
if not resp.ok: if not resp.ok:
LOG.debug("Request returned failure status %s." % resp.status_code) LOG.debug("Request returned failure status %s." % resp.status_code)
raise exc.from_response(resp, resp.content) raise exc.from_response(resp, resp.content)
elif resp.status_code == requests.codes.MULTIPLE_CHOICES: elif (resp.status_code == requests.codes.MULTIPLE_CHOICES and
resp.request.path_url != '/versions'):
# NOTE(flaper87): Eventually, we'll remove the check on `versions`
# which is a bug (1491350) on the server.
raise exc.from_response(resp) raise exc.from_response(resp)
content_type = resp.headers.get('Content-Type') content_type = resp.headers.get('Content-Type')

View File

@@ -553,7 +553,7 @@ class OpenStackImagesShell(object):
client = glanceclient.Client(api_version, endpoint, **kwargs) client = glanceclient.Client(api_version, endpoint, **kwargs)
return client return client
def _cache_schemas(self, options, home_dir='~/.glanceclient'): def _cache_schemas(self, options, client, home_dir='~/.glanceclient'):
homedir = os.path.expanduser(home_dir) homedir = os.path.expanduser(home_dir)
path_prefix = homedir path_prefix = homedir
if options.os_auth_url: if options.os_auth_url:
@@ -573,16 +573,11 @@ class OpenStackImagesShell(object):
schema_file_paths = [os.path.join(path_prefix, x + '_schema.json') schema_file_paths = [os.path.join(path_prefix, x + '_schema.json')
for x in ['image', 'namespace', 'resource_type']] for x in ['image', 'namespace', 'resource_type']]
client = None
failed_download_schema = 0 failed_download_schema = 0
for resource, schema_file_path in zip(resources, schema_file_paths): for resource, schema_file_path in zip(resources, schema_file_paths):
if (not os.path.exists(schema_file_path)) or options.get_schema: if (not os.path.exists(schema_file_path)) or options.get_schema:
try: try:
if not client:
client = self._get_versioned_client('2', options,
force_auth=True)
schema = client.schemas.get(resource) schema = client.schemas.get(resource)
with open(schema_file_path, 'w') as f: with open(schema_file_path, 'w') as f:
f.write(json.dumps(schema.raw())) f.write(json.dumps(schema.raw()))
except Exception: except Exception:
@@ -624,8 +619,21 @@ class OpenStackImagesShell(object):
"Supported values are %s" % SUPPORTED_VERSIONS) "Supported values are %s" % SUPPORTED_VERSIONS)
utils.exit(msg=msg) utils.exit(msg=msg)
if api_version == 2: if not options.os_image_api_version and api_version == 2:
switch_version = self._cache_schemas(options) switch_version = True
client = self._get_versioned_client('2', options,
force_auth=True)
resp, body = client.http_client.get('/versions')
for version in body['versions']:
if version['id'].startswith('v2'):
# NOTE(flaper87): We know v2 is enabled in the server,
# which means we should be able to get the schemas and
# move on.
switch_version = self._cache_schemas(options, client)
break
if switch_version: if switch_version:
print('WARNING: The client is falling back to v1 because' print('WARNING: The client is falling back to v1 because'
' the accessing to v2 failed. This behavior will' ' the accessing to v2 failed. This behavior will'

View File

@@ -80,7 +80,7 @@ class SimpleReadOnlyGlanceClientTest(base.ClientTestBase):
params=param_image_id) params=param_image_id)
def test_help(self): def test_help(self):
help_text = self.glance('help') help_text = self.glance('--os-image-api-version 2 help')
lines = help_text.split('\n') lines = help_text.split('\n')
self.assertFirstLineStartsWith(lines, 'usage: glance') self.assertFirstLineStartsWith(lines, 'usage: glance')

View File

@@ -147,17 +147,18 @@ class ShellTest(testutils.TestCase):
def test_help_unknown_command(self): def test_help_unknown_command(self):
shell = openstack_shell.OpenStackImagesShell() shell = openstack_shell.OpenStackImagesShell()
argstr = 'help foofoo' argstr = '--os-image-api-version 2 help foofoo'
self.assertRaises(exc.CommandError, shell.main, argstr.split()) self.assertRaises(exc.CommandError, shell.main, argstr.split())
def test_help(self): def test_help(self):
shell = openstack_shell.OpenStackImagesShell() shell = openstack_shell.OpenStackImagesShell()
argstr = 'help' argstr = '--os-image-api-version 2 help'
actual = shell.main(argstr.split()) actual = shell.main(argstr.split())
self.assertEqual(0, actual) self.assertEqual(0, actual)
def test_help_on_subcommand_error(self): def test_help_on_subcommand_error(self):
self.assertRaises(exc.CommandError, shell, 'help bad') self.assertRaises(exc.CommandError, shell,
'--os-image-api-version 2 help bad')
def test_help_v2_no_schema(self): def test_help_v2_no_schema(self):
shell = openstack_shell.OpenStackImagesShell() shell = openstack_shell.OpenStackImagesShell()
@@ -185,7 +186,9 @@ class ShellTest(testutils.TestCase):
def test_cert_and_key_args_interchangeable(self, def test_cert_and_key_args_interchangeable(self,
mock_versioned_client): mock_versioned_client):
# make sure --os-cert and --os-key are passed correctly # make sure --os-cert and --os-key are passed correctly
args = '--os-cert mycert --os-key mykey image-list' args = ('--os-image-api-version 2 '
'--os-cert mycert '
'--os-key mykey image-list')
shell(args) shell(args)
assert mock_versioned_client.called assert mock_versioned_client.called
((api_version, args), kwargs) = mock_versioned_client.call_args ((api_version, args), kwargs) = mock_versioned_client.call_args
@@ -193,7 +196,9 @@ class ShellTest(testutils.TestCase):
self.assertEqual('mykey', args.os_key) self.assertEqual('mykey', args.os_key)
# make sure we get the same thing with --cert-file and --key-file # make sure we get the same thing with --cert-file and --key-file
args = '--cert-file mycertfile --key-file mykeyfile image-list' args = ('--os-image-api-version 2 '
'--cert-file mycertfile '
'--key-file mykeyfile image-list')
glance_shell = openstack_shell.OpenStackImagesShell() glance_shell = openstack_shell.OpenStackImagesShell()
glance_shell.main(args.split()) glance_shell.main(args.split())
assert mock_versioned_client.called assert mock_versioned_client.called
@@ -381,6 +386,34 @@ class ShellTest(testutils.TestCase):
msg = 'Unable to import module. Re-run with --debug for more info.' msg = 'Unable to import module. Re-run with --debug for more info.'
self.assertEqual(msg, str(e)) self.assertEqual(msg, str(e))
@mock.patch('glanceclient.v2.client.Client')
@mock.patch('glanceclient.v1.images.ImageManager.list')
def test_shell_v1_fallback_from_v2(self, v1_imgs, v2_client):
self.make_env()
cli2 = mock.MagicMock()
v2_client.return_value = cli2
cli2.http_client.get.return_value = (None, {'versions': []})
args = 'image-list'
glance_shell = openstack_shell.OpenStackImagesShell()
glance_shell.main(args.split())
self.assertFalse(cli2.schemas.get.called)
self.assertTrue(v1_imgs.called)
@mock.patch.object(openstack_shell.OpenStackImagesShell,
'_cache_schemas')
@mock.patch('glanceclient.v2.client.Client')
def test_shell_no_fallback_from_v2(self, v2_client, cache_schemas):
self.make_env()
cli2 = mock.MagicMock()
v2_client.return_value = cli2
cli2.http_client.get.return_value = (None,
{'versions': [{'id': 'v2'}]})
cache_schemas.return_value = False
args = 'image-list'
glance_shell = openstack_shell.OpenStackImagesShell()
glance_shell.main(args.split())
self.assertTrue(cli2.images.list.called)
@mock.patch('glanceclient.v1.client.Client') @mock.patch('glanceclient.v1.client.Client')
def test_auth_plugin_invocation_without_username_with_v1(self, v1_client): def test_auth_plugin_invocation_without_username_with_v1(self, v1_client):
self.make_env(exclude='OS_USERNAME') self.make_env(exclude='OS_USERNAME')
@@ -477,7 +510,7 @@ class ShellTestWithKeystoneV3Auth(ShellTest):
self.assertRaises(exc.CommandError, glance_shell.main, args.split()) self.assertRaises(exc.CommandError, glance_shell.main, args.split())
def test_bash_completion(self): def test_bash_completion(self):
stdout, stderr = self.shell('bash_completion') stdout, stderr = self.shell('--os-image-api-version 2 bash_completion')
# just check we have some output # just check we have some output
required = [ required = [
'--status', '--status',
@@ -542,8 +575,9 @@ class ShellCacheSchemaTest(testutils.TestCase):
} }
schema_odict = OrderedDict(self.schema_dict) schema_odict = OrderedDict(self.schema_dict)
self.shell._cache_schemas(self._make_args(options), args = self._make_args(options)
home_dir=self.cache_dir) client = self.shell._get_versioned_client('2', args, force_auth=True)
self.shell._cache_schemas(args, client, home_dir=self.cache_dir)
self.assertEqual(12, open.mock_calls.__len__()) self.assertEqual(12, open.mock_calls.__len__())
self.assertEqual(mock.call(self.cache_files[0], 'w'), self.assertEqual(mock.call(self.cache_files[0], 'w'),
@@ -564,8 +598,9 @@ class ShellCacheSchemaTest(testutils.TestCase):
} }
schema_odict = OrderedDict(self.schema_dict) schema_odict = OrderedDict(self.schema_dict)
self.shell._cache_schemas(self._make_args(options), args = self._make_args(options)
home_dir=self.cache_dir) client = self.shell._get_versioned_client('2', args, force_auth=True)
self.shell._cache_schemas(args, client, home_dir=self.cache_dir)
self.assertEqual(12, open.mock_calls.__len__()) self.assertEqual(12, open.mock_calls.__len__())
self.assertEqual(mock.call(self.cache_files[0], 'w'), self.assertEqual(mock.call(self.cache_files[0], 'w'),
@@ -585,8 +620,9 @@ class ShellCacheSchemaTest(testutils.TestCase):
'os_auth_url': self.os_auth_url 'os_auth_url': self.os_auth_url
} }
client = mock.MagicMock()
self.shell._cache_schemas(self._make_args(options), self.shell._cache_schemas(self._make_args(options),
home_dir=self.cache_dir) client, home_dir=self.cache_dir)
os.path.exists.assert_any_call(self.prefix_path) os.path.exists.assert_any_call(self.prefix_path)
os.path.exists.assert_any_call(self.cache_files[0]) os.path.exists.assert_any_call(self.cache_files[0])
@@ -604,6 +640,8 @@ class ShellCacheSchemaTest(testutils.TestCase):
self.client.schemas.get.return_value = Exception() self.client.schemas.get.return_value = Exception()
client = mock.MagicMock()
switch_version = self.shell._cache_schemas(self._make_args(options), switch_version = self.shell._cache_schemas(self._make_args(options),
client,
home_dir=self.cache_dir) home_dir=self.cache_dir)
self.assertEqual(switch_version, True) self.assertEqual(switch_version, True)