Fix the issue in tempest test for volumes
1. What is the problem Glance V1 API has been deprecated, so the V2 API should be used instead. And pagination tempest test cases were added, but Trio2o doesn't support volumes pagination yet. 2. What is the solution to the problem Use V2 API in Glance client, and add pagination support for cinder volumes. 3. What the features need to be implemented to the Trio2o to realize the solution N/A Change-Id: Ia580cc5f848be82bfc1b880f3fcdf8d7d2615789
This commit is contained in:
parent
625f46c38e
commit
54528b0381
@ -1,7 +1,7 @@
|
||||
# The order of packages is significant, because pip processes them in the order
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
hacking<0.11,>=0.10.2
|
||||
hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
|
||||
|
||||
coverage>=4.0 # Apache-2.0
|
||||
fixtures>=3.0.0 # Apache-2.0/BSD
|
||||
|
@ -157,7 +157,7 @@ class VolumeController(rest.RestController):
|
||||
context = t_context.extract_context_from_environ()
|
||||
|
||||
if _id == 'detail':
|
||||
return {'volumes': self._get_all(context)}
|
||||
return self._get_all(context)
|
||||
|
||||
# TODO(joehuang): get the release of top and bottom
|
||||
t_release = cons.R_MITAKA
|
||||
@ -218,12 +218,14 @@ class VolumeController(rest.RestController):
|
||||
# now combined with 'detail'
|
||||
|
||||
context = t_context.extract_context_from_environ()
|
||||
return {'volumes': self._get_all(context)}
|
||||
return self._get_all(context)
|
||||
|
||||
def _get_all(self, context):
|
||||
|
||||
# TODO(joehuang): query optimization for pagination, sort, etc
|
||||
ret = []
|
||||
ret = {}
|
||||
ret['volumes'] = []
|
||||
|
||||
pods = az_ag.list_pods_by_tenant(context, self.tenant_id)
|
||||
for pod in pods:
|
||||
if pod['pod_name'] == '':
|
||||
@ -278,7 +280,10 @@ class VolumeController(rest.RestController):
|
||||
|
||||
vol['availability_zone'] = pod['az_name']
|
||||
|
||||
ret.extend(b_ret_body['volumes'])
|
||||
ret['volumes'].extend(b_ret_body['volumes'])
|
||||
|
||||
if b_ret_body.get('volumes_links'):
|
||||
ret['volumes_links'] = b_ret_body['volumes_links']
|
||||
return ret
|
||||
|
||||
@expose(generic=True, template='json')
|
||||
|
@ -229,8 +229,6 @@ class Client(object):
|
||||
|
||||
def _get_config_with_retry(self, cxt, filters, pod, service, retry):
|
||||
conf_list = api.list_pod_service_configurations(cxt, filters)
|
||||
if len(conf_list) > 1:
|
||||
raise exceptions.EndpointNotUnique(pod, service)
|
||||
if len(conf_list) == 0:
|
||||
if not retry:
|
||||
raise exceptions.EndpointNotFound(pod, service)
|
||||
@ -295,7 +293,7 @@ class Client(object):
|
||||
cxt, config_filters)
|
||||
|
||||
if len(config_list) > 1:
|
||||
raise exceptions.EndpointNotUnique(pod_id, service)
|
||||
continue
|
||||
if len(config_list) == 1:
|
||||
config_id = config_list[0]['service_id']
|
||||
update_dict = {
|
||||
|
@ -84,7 +84,7 @@ class GlanceResourceHandle(ResourceHandle):
|
||||
support_resource = {'image': LIST | GET}
|
||||
|
||||
def _get_client(self, cxt):
|
||||
return g_client.Client('1',
|
||||
return g_client.Client('2',
|
||||
token=cxt.auth_token,
|
||||
auth_url=self.auth_url,
|
||||
endpoint=self.endpoint_url,
|
||||
@ -105,7 +105,7 @@ class GlanceResourceHandle(ResourceHandle):
|
||||
try:
|
||||
client = self._get_client(cxt)
|
||||
collection = '%ss' % resource
|
||||
return getattr(client, collection).get(resource_id).to_dict()
|
||||
return getattr(client, collection).get(resource_id)
|
||||
except g_exceptions.InvalidEndpoint:
|
||||
self.endpoint_url = None
|
||||
raise exceptions.EndpointNotAvailable('glance',
|
||||
|
@ -23,6 +23,16 @@ from trio2o.common.i18n import _
|
||||
from trio2o.common import utils
|
||||
import trio2o.db.api as db_api
|
||||
|
||||
SUPPORTED_FILTERS = {
|
||||
'name': 'name',
|
||||
'status': 'status',
|
||||
'changes-since': 'changes-since',
|
||||
'server': 'property-instance_uuid',
|
||||
'type': 'property-image_type',
|
||||
'minRam': 'min_ram',
|
||||
'minDisk': 'min_disk',
|
||||
}
|
||||
|
||||
|
||||
class ImageController(rest.RestController):
|
||||
|
||||
@ -90,27 +100,58 @@ class ImageController(rest.RestController):
|
||||
'minRam': int(image.get('min_ram') or 0),
|
||||
'minDisk': int(image.get('min_disk') or 0),
|
||||
'metadata': image.get('properties', {}),
|
||||
'created': self._format_date(image.get('created_at')),
|
||||
'updated': self._format_date(image.get('updated_at')),
|
||||
'created': image.get('created_at'),
|
||||
'updated': image.get('updated_at'),
|
||||
'status': self._get_status(image),
|
||||
'progress': self._get_progress(image),
|
||||
'links': self._get_links(context, image)
|
||||
}
|
||||
|
||||
@expose(generic=True, template='json')
|
||||
def get_one(self, _id):
|
||||
def get_one(self, _id, **kwargs):
|
||||
context = t_context.extract_context_from_environ()
|
||||
if _id == 'detail':
|
||||
return self.get_all()
|
||||
return self.get_all(**kwargs)
|
||||
image = self.client.get_images(context, _id)
|
||||
if not image:
|
||||
return utils.format_nova_error(404, _('Image not found'))
|
||||
return {'image': self._construct_show_image_entry(context, image)}
|
||||
|
||||
@expose(generic=True, template='json')
|
||||
def get_all(self):
|
||||
def get_all(self, **kwargs):
|
||||
context = t_context.extract_context_from_environ()
|
||||
images = self.client.list_images(context)
|
||||
filters = self._get_filters(kwargs)
|
||||
filters = [{'key': key,
|
||||
'comparator': 'eq',
|
||||
'value': value} for key, value in filters.iteritems()]
|
||||
images = self.client.list_images(context, filters=filters)
|
||||
ret_images = [self._construct_list_image_entry(
|
||||
context, image) for image in images]
|
||||
return {'images': ret_images}
|
||||
|
||||
def _get_filters(self, params):
|
||||
"""Return a dictionary of query param filters from the request.
|
||||
|
||||
:param params: the URI params coming from the wsgi layer
|
||||
:return a dict of key/value filters
|
||||
"""
|
||||
filters = {}
|
||||
for param in params:
|
||||
if param in SUPPORTED_FILTERS or param.startswith('property-'):
|
||||
# map filter name or carry through if property-*
|
||||
filter_name = SUPPORTED_FILTERS.get(param, param)
|
||||
filters[filter_name] = params.get(param)
|
||||
|
||||
# ensure server filter is the instance uuid
|
||||
filter_name = 'property-instance_uuid'
|
||||
try:
|
||||
filters[filter_name] = filters[filter_name].rsplit('/', 1)[1]
|
||||
except (AttributeError, IndexError, KeyError):
|
||||
pass
|
||||
|
||||
filter_name = 'status'
|
||||
if filter_name in filters:
|
||||
# The Image API expects us to use lowercase strings for status
|
||||
filters[filter_name] = filters[filter_name].lower()
|
||||
|
||||
return filters
|
||||
|
@ -223,19 +223,6 @@ class ClientTest(unittest.TestCase):
|
||||
FAKE_RESOURCE, self.context, [])
|
||||
self.assertEqual(resources, [{'name': 'res1'}, {'name': 'res2'}])
|
||||
|
||||
def test_list_endpoint_not_unique(self):
|
||||
# add a new configuration with same pod and service type
|
||||
config_dict = {
|
||||
'service_id': FAKE_SERVICE_ID + '_new',
|
||||
'pod_id': FAKE_SITE_ID,
|
||||
'service_type': FAKE_TYPE,
|
||||
'service_url': FAKE_URL
|
||||
}
|
||||
api.create_pod_service_configuration(self.context, config_dict)
|
||||
self.assertRaises(exceptions.EndpointNotUnique,
|
||||
self.client.list_resources,
|
||||
FAKE_RESOURCE, self.context, [])
|
||||
|
||||
def test_list_endpoint_not_valid(self):
|
||||
cfg.CONF.set_override(name='auto_refresh_endpoint', override=False,
|
||||
group='client')
|
||||
|
Loading…
Reference in New Issue
Block a user