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:
parent
c03ec08276
commit
f9fd69e9c6
@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Added ``/instances/detail`` endpoint to fetch list of instances with details.
|
@ -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",
|
||||
|
@ -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'
|
||||
|
@ -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',
|
||||
|
@ -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."""
|
||||
|
@ -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']
|
||||
|
||||
|
||||
|
@ -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',
|
||||
|
Loading…
Reference in New Issue
Block a user