api: Add response body schemas for hypervisors APIs (3/3)
We split this one up due to its size, which itself is mainly due to the amount of aliasing that went on in early versions as well as the amount of changes that have been made over the years. This focuses on the statistics view. We also reorder the output fields in the view alphabetically just to make reviewing the schema slightly easier. Change-Id: I950a7e2286d451b37b2f7cbd02c4a0a82ac64361 Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
@@ -37,6 +37,7 @@ from nova import utils
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@validation.validated
|
||||
class HypervisorsController(wsgi.Controller):
|
||||
"""The Hypervisors API controller for the OpenStack API."""
|
||||
|
||||
@@ -516,6 +517,7 @@ class HypervisorsController(wsgi.Controller):
|
||||
@wsgi.api_version('2.1', '2.87')
|
||||
@wsgi.expected_errors(())
|
||||
@validation.query_schema(schema.statistics_query)
|
||||
@validation.response_body_schema(schema.statistics_response, '2.1', '2.87')
|
||||
def statistics(self, req):
|
||||
"""Prior to microversion 2.88, you could get statistics for the
|
||||
hypervisor. Most of these are now accessible from placement and the few
|
||||
@@ -524,4 +526,4 @@ class HypervisorsController(wsgi.Controller):
|
||||
context = req.environ['nova.context']
|
||||
context.can(hv_policies.BASE_POLICY_NAME % 'statistics', target={})
|
||||
stats = self.host_api.compute_node_statistics(context)
|
||||
return dict(hypervisor_statistics=stats)
|
||||
return {'hypervisor_statistics': stats}
|
||||
|
@@ -305,3 +305,43 @@ uptime_response_v253['properties']['hypervisor']['properties'].update({
|
||||
'uptime': {'type': ['string', 'null']}
|
||||
})
|
||||
uptime_response_v253['properties']['hypervisor']['required'].append('uptime')
|
||||
|
||||
statistics_response = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'hypervisor_statistics': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'count': {'type': 'integer'},
|
||||
'current_workload': {'type': 'integer'},
|
||||
'disk_available_least': {'type': 'integer'},
|
||||
'free_disk_gb': {'type': 'integer'},
|
||||
'free_ram_mb': {'type': 'integer'},
|
||||
'local_gb': {'type': 'integer'},
|
||||
'local_gb_used': {'type': 'integer'},
|
||||
'memory_mb': {'type': 'integer'},
|
||||
'memory_mb_used': {'type': 'integer'},
|
||||
'running_vms': {'type': 'integer'},
|
||||
'vcpus': {'type': 'integer'},
|
||||
'vcpus_used': {'type': 'integer'},
|
||||
},
|
||||
'required': [
|
||||
'count',
|
||||
'current_workload',
|
||||
'disk_available_least',
|
||||
'free_disk_gb',
|
||||
'free_ram_mb',
|
||||
'local_gb',
|
||||
'local_gb_used',
|
||||
'memory_mb',
|
||||
'memory_mb_used',
|
||||
'running_vms',
|
||||
'vcpus',
|
||||
'vcpus_used',
|
||||
],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
'required': ['hypervisor_statistics'],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
@@ -949,51 +949,50 @@ def compute_node_statistics(context):
|
||||
agg_cols = [
|
||||
func.count().label('count'),
|
||||
sql.func.sum(
|
||||
inner_sel.c.vcpus
|
||||
).label('vcpus'),
|
||||
inner_sel.c.current_workload
|
||||
).label('current_workload'),
|
||||
sql.func.sum(
|
||||
inner_sel.c.memory_mb
|
||||
).label('memory_mb'),
|
||||
sql.func.sum(
|
||||
inner_sel.c.local_gb
|
||||
).label('local_gb'),
|
||||
sql.func.sum(
|
||||
inner_sel.c.vcpus_used
|
||||
).label('vcpus_used'),
|
||||
sql.func.sum(
|
||||
inner_sel.c.memory_mb_used
|
||||
).label('memory_mb_used'),
|
||||
sql.func.sum(
|
||||
inner_sel.c.local_gb_used
|
||||
).label('local_gb_used'),
|
||||
sql.func.sum(
|
||||
inner_sel.c.free_ram_mb
|
||||
).label('free_ram_mb'),
|
||||
inner_sel.c.disk_available_least
|
||||
).label('disk_available_least'),
|
||||
sql.func.sum(
|
||||
inner_sel.c.free_disk_gb
|
||||
).label('free_disk_gb'),
|
||||
sql.func.sum(
|
||||
inner_sel.c.current_workload
|
||||
).label('current_workload'),
|
||||
inner_sel.c.free_ram_mb
|
||||
).label('free_ram_mb'),
|
||||
sql.func.sum(
|
||||
inner_sel.c.local_gb
|
||||
).label('local_gb'),
|
||||
sql.func.sum(
|
||||
inner_sel.c.local_gb_used
|
||||
).label('local_gb_used'),
|
||||
sql.func.sum(
|
||||
inner_sel.c.memory_mb
|
||||
).label('memory_mb'),
|
||||
sql.func.sum(
|
||||
inner_sel.c.memory_mb_used
|
||||
).label('memory_mb_used'),
|
||||
sql.func.sum(
|
||||
inner_sel.c.running_vms
|
||||
).label('running_vms'),
|
||||
sql.func.sum(
|
||||
inner_sel.c.disk_available_least
|
||||
).label('disk_available_least'),
|
||||
inner_sel.c.vcpus
|
||||
).label('vcpus'),
|
||||
sql.func.sum(
|
||||
inner_sel.c.vcpus_used
|
||||
).label('vcpus_used'),
|
||||
]
|
||||
select = sql.select(*agg_cols).select_from(j)
|
||||
|
||||
with engine.connect() as conn, conn.begin():
|
||||
results = conn.execute(select).fetchone()
|
||||
results = conn.execute(select).mappings().fetchone()
|
||||
|
||||
# Build a dict of the info--making no assumptions about result
|
||||
fields = ('count', 'vcpus', 'memory_mb', 'local_gb', 'vcpus_used',
|
||||
'memory_mb_used', 'local_gb_used', 'free_ram_mb', 'free_disk_gb',
|
||||
'current_workload', 'running_vms', 'disk_available_least')
|
||||
results = {field: int(results[idx] or 0)
|
||||
for idx, field in enumerate(fields)}
|
||||
return results
|
||||
fields = (
|
||||
'count', 'current_workload', 'disk_available_least', 'free_disk_gb',
|
||||
'free_ram_mb', 'local_gb', 'local_gb_used', 'memory_mb',
|
||||
'memory_mb_used', 'running_vms', 'vcpus', 'vcpus_used')
|
||||
return {field: int(results[field] or 0) for field in fields}
|
||||
|
||||
|
||||
###################
|
||||
|
@@ -69,6 +69,22 @@ class HypervisorsPolicyTest(base.BasePolicyTest):
|
||||
vcpus_used=8,
|
||||
),
|
||||
)
|
||||
self.controller.host_api.compute_node_statistics = mock.MagicMock(
|
||||
return_value={
|
||||
'count': 0,
|
||||
'current_workload': 0,
|
||||
'disk_available_least': 0,
|
||||
'free_disk_gb': 0,
|
||||
'free_ram_mb': 0,
|
||||
'local_gb': 0,
|
||||
'local_gb_used': 0,
|
||||
'memory_mb': 0,
|
||||
'memory_mb_used': 0,
|
||||
'running_vms': 0,
|
||||
'vcpus': 0,
|
||||
'vcpus_used': 0,
|
||||
}
|
||||
)
|
||||
self.controller.host_api.get_host_uptime = mock.MagicMock(
|
||||
return_value=None
|
||||
)
|
||||
@@ -117,8 +133,7 @@ class HypervisorsPolicyTest(base.BasePolicyTest):
|
||||
rule_name, self.controller.servers,
|
||||
self.req, '123')
|
||||
|
||||
@mock.patch('nova.compute.api.HostAPI.compute_node_statistics')
|
||||
def test_statistics_hypervisors_policy(self, mock_statistics):
|
||||
def test_statistics_hypervisors_policy(self):
|
||||
rule_name = hv_policies.BASE_POLICY_NAME % 'statistics'
|
||||
self.common_policy_auth(self.project_admin_authorized_contexts,
|
||||
rule_name, self.controller.statistics,
|
||||
|
Reference in New Issue
Block a user