diff options
| author | Jenkins <jenkins@review.openstack.org> | 2012-07-24 03:28:12 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2012-07-24 03:28:12 +0000 |
| commit | 4d882ab978055b0b4199a749f4c243cfd53425ef (patch) | |
| tree | c8bb2aac83b377ed832fa202d061bda1764d8a9a /nova | |
| parent | 8a164f5e05509307720ad8a8f39ab1f352553098 (diff) | |
| parent | 09d978994325b28c76050f112af3ee66b84a5e1f (diff) | |
Merge "Add call to get hypervisor statistics"
Diffstat (limited to 'nova')
| -rw-r--r-- | nova/api/openstack/compute/contrib/hypervisors.py | 30 | ||||
| -rw-r--r-- | nova/db/api.py | 5 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/api.py | 24 | ||||
| -rw-r--r-- | nova/tests/api/openstack/compute/contrib/test_hypervisors.py | 74 |
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) |
