summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2012-07-24 03:28:12 +0000
committerGerrit Code Review <review@openstack.org>2012-07-24 03:28:12 +0000
commit4d882ab978055b0b4199a749f4c243cfd53425ef (patch)
treec8bb2aac83b377ed832fa202d061bda1764d8a9a /nova
parent8a164f5e05509307720ad8a8f39ab1f352553098 (diff)
parent09d978994325b28c76050f112af3ee66b84a5e1f (diff)
Merge "Add call to get hypervisor statistics"
Diffstat (limited to 'nova')
-rw-r--r--nova/api/openstack/compute/contrib/hypervisors.py30
-rw-r--r--nova/db/api.py5
-rw-r--r--nova/db/sqlalchemy/api.py24
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_hypervisors.py74
4 files changed, 130 insertions, 3 deletions
diff --git a/nova/api/openstack/compute/contrib/hypervisors.py b/nova/api/openstack/compute/contrib/hypervisors.py
index 49b050871..33aaa014b 100644
--- a/nova/api/openstack/compute/contrib/hypervisors.py
+++ b/nova/api/openstack/compute/contrib/hypervisors.py
@@ -104,6 +104,26 @@ class HypervisorServersTemplate(xmlutil.TemplateBuilder):
return xmlutil.MasterTemplate(root, 1)
+class HypervisorStatisticsTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('hypervisor_statistics',
+ selector='hypervisor_statistics')
+ root.set('count')
+ root.set('vcpus')
+ root.set('memory_mb')
+ root.set('local_gb')
+ root.set('vcpus_used')
+ root.set('memory_mb_used')
+ root.set('local_gb_used')
+ root.set('free_ram_mb')
+ root.set('free_disk_gb')
+ root.set('current_workload')
+ root.set('running_vms')
+ root.set('disk_available_least')
+
+ return xmlutil.MasterTemplate(root, 1)
+
+
class HypervisorsController(object):
"""The Hypervisors API controller for the OpenStack API."""
@@ -211,6 +231,13 @@ class HypervisorsController(object):
msg = _("No hypervisor matching '%s' could be found.") % id
raise webob.exc.HTTPNotFound(explanation=msg)
+ @wsgi.serializers(xml=HypervisorStatisticsTemplate)
+ def statistics(self, req):
+ context = req.environ['nova.context']
+ authorize(context)
+ stats = db.compute_node_statistics(context)
+ return dict(hypervisor_statistics=stats)
+
class Hypervisors(extensions.ExtensionDescriptor):
"""Admin-only hypervisor administration"""
@@ -223,7 +250,8 @@ class Hypervisors(extensions.ExtensionDescriptor):
def get_resources(self):
resources = [extensions.ResourceExtension('os-hypervisors',
HypervisorsController(),
- collection_actions={'detail': 'GET'},
+ collection_actions={'detail': 'GET',
+ 'statistics': 'GET'},
member_actions={'uptime': 'GET',
'search': 'GET',
'servers': 'GET'})]
diff --git a/nova/db/api.py b/nova/db/api.py
index be1a20a10..231df02f2 100644
--- a/nova/db/api.py
+++ b/nova/db/api.py
@@ -232,6 +232,11 @@ def compute_node_utilization_set(context, host, free_ram_mb=None,
return IMPL.compute_node_utilization_set(context, host, free_ram_mb,
free_disk_gb, work, vms)
+
+def compute_node_statistics(context):
+ return IMPL.compute_node_statistics(context)
+
+
###################
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index f3bcb5c1e..946cac780 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -630,6 +630,30 @@ def compute_node_utilization_set(context, host, free_ram_mb=None,
return compute_node
+def compute_node_statistics(context):
+ """Compute statistics over all compute nodes."""
+ result = model_query(context,
+ func.count(models.ComputeNode.id),
+ func.sum(models.ComputeNode.vcpus),
+ func.sum(models.ComputeNode.memory_mb),
+ func.sum(models.ComputeNode.local_gb),
+ func.sum(models.ComputeNode.vcpus_used),
+ func.sum(models.ComputeNode.memory_mb_used),
+ func.sum(models.ComputeNode.local_gb_used),
+ func.sum(models.ComputeNode.free_ram_mb),
+ func.sum(models.ComputeNode.free_disk_gb),
+ func.sum(models.ComputeNode.current_workload),
+ func.sum(models.ComputeNode.running_vms),
+ func.sum(models.ComputeNode.disk_available_least),
+ read_deleted="no").first()
+
+ # 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')
+ return dict((field, result[idx] or 0) for idx, field in enumerate(fields))
+
+
###################
diff --git a/nova/tests/api/openstack/compute/contrib/test_hypervisors.py b/nova/tests/api/openstack/compute/contrib/test_hypervisors.py
index 6a9a1fc25..740477ca3 100644
--- a/nova/tests/api/openstack/compute/contrib/test_hypervisors.py
+++ b/nova/tests/api/openstack/compute/contrib/test_hypervisors.py
@@ -94,6 +94,32 @@ def fake_compute_node_get(context, compute_id):
raise exception.ComputeHostNotFound
+def fake_compute_node_statistics(context):
+ result = dict(
+ count=0,
+ vcpus=0,
+ memory_mb=0,
+ local_gb=0,
+ vcpus_used=0,
+ memory_mb_used=0,
+ local_gb_used=0,
+ free_ram_mb=0,
+ free_disk_gb=0,
+ current_workload=0,
+ running_vms=0,
+ disk_available_least=0,
+ )
+
+ for hyper in TEST_HYPERS:
+ for key in result:
+ if key == 'count':
+ result[key] += 1
+ else:
+ result[key] += hyper[key]
+
+ return result
+
+
def fake_instance_get_all_by_host(context, host):
results = []
for inst in TEST_SERVERS:
@@ -113,6 +139,8 @@ class HypervisorsTest(test.TestCase):
fake_compute_node_search_by_hypervisor)
self.stubs.Set(db, 'compute_node_get',
fake_compute_node_get)
+ self.stubs.Set(db, 'compute_node_statistics',
+ fake_compute_node_statistics)
self.stubs.Set(db, 'instance_get_all_by_host',
fake_instance_get_all_by_host)
@@ -285,11 +313,27 @@ class HypervisorsTest(test.TestCase):
dict(name="inst2", uuid="uuid2"),
dict(name="inst4", uuid="uuid4")])]))
+ def test_statistics(self):
+ req = fakes.HTTPRequest.blank('/v2/fake/os-hypervisors/statistics')
+ result = self.controller.statistics(req)
+
+ self.assertEqual(result, dict(hypervisor_statistics=dict(
+ count=2,
+ vcpus=8,
+ memory_mb=20 * 1024,
+ local_gb=500,
+ vcpus_used=4,
+ memory_mb_used=10 * 1024,
+ local_gb_used=250,
+ free_ram_mb=10 * 1024,
+ free_disk_gb=250,
+ current_workload=4,
+ running_vms=4,
+ disk_available_least=200)))
+
class HypervisorsSerializersTest(test.TestCase):
def compare_to_exemplar(self, exemplar, hyper):
- self.assertEqual('hypervisor', hyper.tag)
-
# Check attributes
for key, value in exemplar.items():
if key in ('service', 'servers'):
@@ -332,6 +376,7 @@ class HypervisorsSerializersTest(test.TestCase):
self.assertEqual('hypervisors', tree.tag)
self.assertEqual(len(exemplar['hypervisors']), len(tree))
for idx, hyper in enumerate(tree):
+ self.assertEqual('hypervisor', hyper.tag)
self.compare_to_exemplar(exemplar['hypervisors'][idx], hyper)
def test_detail_serializer(self):
@@ -377,6 +422,7 @@ class HypervisorsSerializersTest(test.TestCase):
self.assertEqual('hypervisors', tree.tag)
self.assertEqual(len(exemplar['hypervisors']), len(tree))
for idx, hyper in enumerate(tree):
+ self.assertEqual('hypervisor', hyper.tag)
self.compare_to_exemplar(exemplar['hypervisors'][idx], hyper)
def test_show_serializer(self):
@@ -402,6 +448,7 @@ class HypervisorsSerializersTest(test.TestCase):
text = serializer.serialize(exemplar)
tree = etree.fromstring(text)
+ self.assertEqual('hypervisor', tree.tag)
self.compare_to_exemplar(exemplar['hypervisor'], tree)
def test_uptime_serializer(self):
@@ -413,6 +460,7 @@ class HypervisorsSerializersTest(test.TestCase):
text = serializer.serialize(exemplar)
tree = etree.fromstring(text)
+ self.assertEqual('hypervisor', tree.tag)
self.compare_to_exemplar(exemplar['hypervisor'], tree)
def test_servers_serializer(self):
@@ -438,4 +486,26 @@ class HypervisorsSerializersTest(test.TestCase):
self.assertEqual('hypervisors', tree.tag)
self.assertEqual(len(exemplar['hypervisors']), len(tree))
for idx, hyper in enumerate(tree):
+ self.assertEqual('hypervisor', hyper.tag)
self.compare_to_exemplar(exemplar['hypervisors'][idx], hyper)
+
+ def test_statistics_serializer(self):
+ serializer = hypervisors.HypervisorStatisticsTemplate()
+ exemplar = dict(hypervisor_statistics=dict(
+ count=2,
+ vcpus=8,
+ memory_mb=20 * 1024,
+ local_gb=500,
+ vcpus_used=4,
+ memory_mb_used=10 * 1024,
+ local_gb_used=250,
+ free_ram_mb=10 * 1024,
+ free_disk_gb=250,
+ current_workload=4,
+ running_vms=4,
+ disk_available_least=200))
+ text = serializer.serialize(exemplar)
+ tree = etree.fromstring(text)
+
+ self.assertEqual('hypervisor_statistics', tree.tag)
+ self.compare_to_exemplar(exemplar['hypervisor_statistics'], tree)