Add detailed list for instances

Currently, listing instances only allows to get basic information about
entities. To get the details, one need to query instance "show" endpoint
for each instance separately. This is inefficient and exposes API to a
heavier load.

There are use cases in which we want to obtain detailed information
about all instances. In particular, in services integrating with Trove.
For example, Vitrage project requires this information to build vertices
and edges in the resource graph for RCA analysis.

Change-Id: I33252cce41c27cc7302c860dde1f6448ecdf3991
Signed-off-by: Bartosz Zurkowski <b.zurkowski@samsung.com>
This commit is contained in:
Bartosz Zurkowski 2018-10-08 13:02:51 +02:00
parent c03ec08276
commit f9fd69e9c6
7 changed files with 63 additions and 6 deletions

View File

@ -0,0 +1,4 @@
---
features:
- |
Added ``/instances/detail`` endpoint to fetch list of instances with details.

View File

@ -85,6 +85,10 @@ class API(wsgi.Router):
controller=instance_resource,
action="index",
conditions={'method': ['GET']})
mapper.connect("/{tenant_id}/instances/detail",
controller=instance_resource,
action="detail",
conditions={'method': ['GET']})
mapper.connect("/{tenant_id}/instances",
controller=instance_resource,
action="create",

View File

@ -15,6 +15,7 @@ from oslo_policy import policy
PATH_BASE = '/v1.0/{account_id}'
PATH_INSTANCES = PATH_BASE + '/instances'
PATH_INSTANCES_DETAIL = PATH_INSTANCES + '/detail'
PATH_INSTANCE = PATH_INSTANCES + '/{instance_id}'
PATH_INSTANCE_ACTION = PATH_INSTANCE + '/action'
PATH_USERS = PATH_INSTANCE + '/users'

View File

@ -13,7 +13,7 @@
from oslo_policy import policy
from trove.common.policies.base import (
PATH_INSTANCES, PATH_INSTANCE, PATH_INSTANCE_ACTION)
PATH_INSTANCES, PATH_INSTANCES_DETAIL, PATH_INSTANCE, PATH_INSTANCE_ACTION)
rules = [
@ -57,6 +57,16 @@ rules = [
'method': 'GET'
}
]),
policy.DocumentedRuleDefault(
name='instance:detail',
check_str='rule:admin_or_owner',
description='List database instances with details.',
operations=[
{
'path': PATH_INSTANCES_DETAIL,
'method': 'GET'
}
]),
policy.DocumentedRuleDefault(
name='instance:show',
check_str='rule:admin_or_owner',

View File

@ -198,13 +198,31 @@ class InstanceController(wsgi.Controller):
LOG.debug("req : '%s'\n\n", req)
context = req.environ[wsgi.CONTEXT_KEY]
policy.authorize_on_tenant(context, 'instance:index')
instances = self._get_instances(req, instance_view=views.InstanceView)
return wsgi.Result(instances, 200)
def detail(self, req, tenant_id):
"""Return all instances with details."""
LOG.info("Listing database instances with details for tenant '%s'",
tenant_id)
LOG.debug("req : '%s'\n\n", req)
context = req.environ[wsgi.CONTEXT_KEY]
policy.authorize_on_tenant(context, 'instance:detail')
instances = self._get_instances(req,
instance_view=views.InstanceDetailView)
return wsgi.Result(instances, 200)
def _get_instances(self, req, instance_view):
context = req.environ[wsgi.CONTEXT_KEY]
clustered_q = req.GET.get('include_clustered', '').lower()
include_clustered = clustered_q == 'true'
servers, marker = models.Instances.load(context, include_clustered)
view = views.InstancesView(servers, req=req)
instances, marker = models.Instances.load(context, include_clustered)
view = views.InstancesView(instances,
item_view=instance_view,
req=req)
paged = pagination.SimplePaginatedDataView(req.url, 'instances', view,
marker)
return wsgi.Result(paged.data(), 200)
return paged.data()
def backups(self, req, tenant_id, id):
"""Return all backups for the specified instance."""

View File

@ -162,8 +162,9 @@ class InstanceDetailView(InstanceView):
class InstancesView(object):
"""Shows a list of SimpleInstance objects."""
def __init__(self, instances, req=None):
def __init__(self, instances, item_view=InstanceView, req=None):
self.instances = instances
self.item_view = item_view
self.req = req
def data(self):
@ -174,7 +175,7 @@ class InstancesView(object):
return {'instances': data}
def data_for_instance(self, instance):
view = InstanceView(instance, req=self.req)
view = self.item_view(instance, req=self.req)
return view.data()['instance']

View File

@ -1179,6 +1179,25 @@ class TestInstanceListing(object):
check.datastore()
check.volume()
@test
def test_detailed_list(self):
allowed_attrs = ['created', 'databases', 'flavor', 'hostname', 'id',
'links', 'name', 'status', 'updated', 'ip',
'datastore', 'fault', 'region']
if VOLUME_SUPPORT:
allowed_attrs.append('volume')
instances = dbaas.instances.list(detailed=True)
assert_equal(200, dbaas.last_http_code)
for instance in instances:
instance_dict = instance._info
with CheckInstance(instance_dict) as check:
check.contains_allowed_attrs(instance_dict, allowed_attrs,
msg="Instance Detailed Index")
check.flavor()
check.datastore()
check.volume()
check.used_volume()
@test
def test_get_instance(self):
allowed_attrs = ['created', 'databases', 'flavor', 'hostname', 'id',