diff --git a/doc/api_samples/all_extensions/extensions-get-resp.json b/doc/api_samples/all_extensions/extensions-get-resp.json
index 4d4967accf7b..0359faf0c41a 100644
--- a/doc/api_samples/all_extensions/extensions-get-resp.json
+++ b/doc/api_samples/all_extensions/extensions-get-resp.json
@@ -312,6 +312,14 @@
"namespace": "http://docs.openstack.org/compute/ext/extended_rescue_with_image/api/v2",
"updated": "2014-01-04T00:00:00Z"
},
+ {
+ "alias": "os-hypervisor-status",
+ "description": "Show hypervisor status.",
+ "links": [],
+ "name": "HypervisorStatus",
+ "namespace": "http://docs.openstack.org/compute/ext/hypervisor_status/api/v1.1",
+ "updated": "2014-04-17T00:00:00Z"
+ },
{
"alias": "os-extended-services",
"description": "Extended services support.",
diff --git a/doc/api_samples/all_extensions/extensions-get-resp.xml b/doc/api_samples/all_extensions/extensions-get-resp.xml
index d69e8ab40ace..ff47a36b951f 100644
--- a/doc/api_samples/all_extensions/extensions-get-resp.xml
+++ b/doc/api_samples/all_extensions/extensions-get-resp.xml
@@ -143,6 +143,9 @@
Extended services deletion support.
+
+ Show hypervisor status.
+
Extended Volumes support.
diff --git a/doc/api_samples/os-hypervisor-status/hypervisors-show-with-status-resp.json b/doc/api_samples/os-hypervisor-status/hypervisors-show-with-status-resp.json
new file mode 100644
index 000000000000..44af92c433a5
--- /dev/null
+++ b/doc/api_samples/os-hypervisor-status/hypervisors-show-with-status-resp.json
@@ -0,0 +1,27 @@
+{
+ "hypervisor": {
+ "cpu_info": "?",
+ "current_workload": 0,
+ "disk_available_least": 0,
+ "free_disk_gb": 1028,
+ "free_ram_mb": 7680,
+ "hypervisor_hostname": "fake-mini",
+ "hypervisor_type": "fake",
+ "hypervisor_version": 1000,
+ "id": 1,
+ "status": "enabled",
+ "state": "up",
+ "local_gb": 1028,
+ "local_gb_used": 0,
+ "memory_mb": 8192,
+ "memory_mb_used": 512,
+ "running_vms": 0,
+ "service": {
+ "host": "5641188ab2964f88a21042b493585ff8",
+ "id": 2,
+ "disabled_reason": null
+ },
+ "vcpus": 1,
+ "vcpus_used": 0
+ }
+}
diff --git a/doc/api_samples/os-hypervisor-status/hypervisors-show-with-status-resp.xml b/doc/api_samples/os-hypervisor-status/hypervisors-show-with-status-resp.xml
new file mode 100644
index 000000000000..dbfec700ce61
--- /dev/null
+++ b/doc/api_samples/os-hypervisor-status/hypervisors-show-with-status-resp.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/doc/v3/api_samples/os-hypervisors/hypervisors-detail-resp.json b/doc/v3/api_samples/os-hypervisors/hypervisors-detail-resp.json
index e800c777ae0c..8694c135a0c8 100644
--- a/doc/v3/api_samples/os-hypervisors/hypervisors-detail-resp.json
+++ b/doc/v3/api_samples/os-hypervisors/hypervisors-detail-resp.json
@@ -3,6 +3,8 @@
{
"cpu_info": "?",
"current_workload": 0,
+ "status": "enabled",
+ "state": "up",
"disk_available_least": 0,
"host_ip": "1.1.1.1",
"free_disk_gb": 1028,
@@ -18,7 +20,8 @@
"running_vms": 0,
"service": {
"host": "e6a37ee802d74863ab8b91ade8f12a67",
- "id": 2
+ "id": 2,
+ "disabled_reason": null
},
"vcpus": 1,
"vcpus_used": 0
diff --git a/doc/v3/api_samples/os-hypervisors/hypervisors-list-resp.json b/doc/v3/api_samples/os-hypervisors/hypervisors-list-resp.json
index 8d94021274fb..375627499df6 100644
--- a/doc/v3/api_samples/os-hypervisors/hypervisors-list-resp.json
+++ b/doc/v3/api_samples/os-hypervisors/hypervisors-list-resp.json
@@ -2,7 +2,9 @@
"hypervisors": [
{
"hypervisor_hostname": "fake-mini",
- "id": 1
+ "id": 1,
+ "state": "up",
+ "status": "enabled"
}
]
-}
\ No newline at end of file
+}
diff --git a/doc/v3/api_samples/os-hypervisors/hypervisors-search-resp.json b/doc/v3/api_samples/os-hypervisors/hypervisors-search-resp.json
index 8d94021274fb..375627499df6 100644
--- a/doc/v3/api_samples/os-hypervisors/hypervisors-search-resp.json
+++ b/doc/v3/api_samples/os-hypervisors/hypervisors-search-resp.json
@@ -2,7 +2,9 @@
"hypervisors": [
{
"hypervisor_hostname": "fake-mini",
- "id": 1
+ "id": 1,
+ "state": "up",
+ "status": "enabled"
}
]
-}
\ No newline at end of file
+}
diff --git a/doc/v3/api_samples/os-hypervisors/hypervisors-servers-resp.json b/doc/v3/api_samples/os-hypervisors/hypervisors-servers-resp.json
index 934ef0c02db7..710b05b9309a 100644
--- a/doc/v3/api_samples/os-hypervisors/hypervisors-servers-resp.json
+++ b/doc/v3/api_samples/os-hypervisors/hypervisors-servers-resp.json
@@ -2,6 +2,8 @@
"hypervisor": {
"hypervisor_hostname": "fake-mini",
"id": 1,
+ "state": "up",
+ "status": "enabled",
"servers": []
}
-}
\ No newline at end of file
+}
diff --git a/doc/v3/api_samples/os-hypervisors/hypervisors-show-resp.json b/doc/v3/api_samples/os-hypervisors/hypervisors-show-resp.json
index 0c4957bdae09..3d2c972ce3cf 100644
--- a/doc/v3/api_samples/os-hypervisors/hypervisors-show-resp.json
+++ b/doc/v3/api_samples/os-hypervisors/hypervisors-show-resp.json
@@ -1,6 +1,8 @@
{
"hypervisor": {
"cpu_info": "?",
+ "state": "up",
+ "status": "enabled",
"current_workload": 0,
"disk_available_least": 0,
"host_ip": "1.1.1.1",
@@ -17,7 +19,8 @@
"running_vms": 0,
"service": {
"host": "043b3cacf6f34c90a7245151fc8ebcda",
- "id": 2
+ "id": 2,
+ "disabled_reason": null
},
"vcpus": 1,
"vcpus_used": 0
diff --git a/doc/v3/api_samples/os-hypervisors/hypervisors-uptime-resp.json b/doc/v3/api_samples/os-hypervisors/hypervisors-uptime-resp.json
index f5f9d19e7ccd..78521b373112 100644
--- a/doc/v3/api_samples/os-hypervisors/hypervisors-uptime-resp.json
+++ b/doc/v3/api_samples/os-hypervisors/hypervisors-uptime-resp.json
@@ -2,6 +2,8 @@
"hypervisor": {
"hypervisor_hostname": "fake-mini",
"id": 1,
+ "state": "up",
+ "status": "enabled",
"uptime": " 08:32:11 up 93 days, 18:25, 12 users, load average: 0.20, 0.12, 0.14"
}
-}
\ No newline at end of file
+}
diff --git a/doc/v3/api_samples/os-pci/hypervisors-pci-detail-resp.json b/doc/v3/api_samples/os-pci/hypervisors-pci-detail-resp.json
index 1ca293225e4e..f6f7363ef43c 100644
--- a/doc/v3/api_samples/os-pci/hypervisors-pci-detail-resp.json
+++ b/doc/v3/api_samples/os-pci/hypervisors-pci-detail-resp.json
@@ -2,6 +2,8 @@
"hypervisors": [
{
"cpu_info": "?",
+ "state": "up",
+ "status": "enabled",
"current_workload": 0,
"disk_available_least": 0,
"host_ip": "1.1.1.1",
@@ -30,7 +32,8 @@
"running_vms": 0,
"service": {
"host": "043b3cacf6f34c90a7245151fc8ebcda",
- "id": 2
+ "id": 2,
+ "disabled_reason": null
},
"vcpus": 1,
"vcpus_used": 0
diff --git a/doc/v3/api_samples/os-pci/hypervisors-pci-show-resp.json b/doc/v3/api_samples/os-pci/hypervisors-pci-show-resp.json
index 2a6e41bf4dbd..f2fa988f83c9 100644
--- a/doc/v3/api_samples/os-pci/hypervisors-pci-show-resp.json
+++ b/doc/v3/api_samples/os-pci/hypervisors-pci-show-resp.json
@@ -4,6 +4,8 @@
"current_workload": 0,
"disk_available_least": 0,
"host_ip": "1.1.1.1",
+ "state": "up",
+ "status": "enabled",
"free_disk_gb": 1028,
"free_ram_mb": 7680,
"hypervisor_hostname": "fake-mini",
@@ -29,7 +31,8 @@
"running_vms": 0,
"service": {
"host": "043b3cacf6f34c90a7245151fc8ebcda",
- "id": 2
+ "id": 2,
+ "disabled_reason": null
},
"vcpus": 1,
"vcpus_used": 0
diff --git a/nova/api/openstack/compute/contrib/hypervisor_status.py b/nova/api/openstack/compute/contrib/hypervisor_status.py
new file mode 100644
index 000000000000..94bcabca48e5
--- /dev/null
+++ b/nova/api/openstack/compute/contrib/hypervisor_status.py
@@ -0,0 +1,25 @@
+# Copyright 2014 Intel Corp.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from nova.api.openstack import extensions
+
+
+class Hypervisor_status(extensions.ExtensionDescriptor):
+ """Show hypervisor status."""
+
+ name = "HypervisorStatus"
+ alias = "os-hypervisor-status"
+ namespace = ("http://docs.openstack.org/compute/ext/"
+ "hypervisor_status/api/v1.1")
+ updated = "2014-04-17T00:00:00Z"
diff --git a/nova/api/openstack/compute/contrib/hypervisors.py b/nova/api/openstack/compute/contrib/hypervisors.py
index 22b51fce740e..d2df93fa8293 100644
--- a/nova/api/openstack/compute/contrib/hypervisors.py
+++ b/nova/api/openstack/compute/contrib/hypervisors.py
@@ -23,6 +23,7 @@ from nova.api.openstack import xmlutil
from nova import compute
from nova import exception
from nova.i18n import _
+from nova import servicegroup
authorize = extensions.extension_authorizer('compute', 'hypervisors')
@@ -31,6 +32,8 @@ authorize = extensions.extension_authorizer('compute', 'hypervisors')
def make_hypervisor(elem, detail):
elem.set('hypervisor_hostname')
elem.set('id')
+ elem.set('state')
+ elem.set('status')
if detail:
elem.set('vcpus')
elem.set('memory_mb')
@@ -52,6 +55,7 @@ def make_hypervisor(elem, detail):
selector='service')
service.set('id')
service.set('host')
+ service.set('disabled_reason')
class HypervisorIndexTemplate(xmlutil.TemplateBuilder):
@@ -128,6 +132,7 @@ class HypervisorsController(object):
def __init__(self, ext_mgr):
self.host_api = compute.HostAPI()
+ self.servicegroup_api = servicegroup.API()
super(HypervisorsController, self).__init__()
self.ext_mgr = ext_mgr
@@ -137,6 +142,13 @@ class HypervisorsController(object):
'hypervisor_hostname': hypervisor['hypervisor_hostname'],
}
+ ext_status_loaded = self.ext_mgr.is_loaded('os-hypervisor-status')
+ if ext_status_loaded:
+ alive = self.servicegroup_api.service_is_up(hypervisor['service'])
+ hyp_dict['state'] = 'up' if alive else "down"
+ hyp_dict['status'] = (
+ 'disabled' if hypervisor['service']['disabled'] else 'enabled')
+
if detail and not servers:
fields = ('vcpus', 'memory_mb', 'local_gb', 'vcpus_used',
'memory_mb_used', 'local_gb_used',
@@ -153,6 +165,9 @@ class HypervisorsController(object):
'id': hypervisor['service_id'],
'host': hypervisor['service']['host'],
}
+ if ext_status_loaded:
+ hyp_dict['service'].update(
+ disabled_reason=hypervisor['service']['disabled_reason'])
if servers:
hyp_dict['servers'] = [dict(name=serv['name'], uuid=serv['uuid'])
diff --git a/nova/api/openstack/compute/plugins/v3/hypervisors.py b/nova/api/openstack/compute/plugins/v3/hypervisors.py
index cf145e6283a1..c38ed4af18a6 100644
--- a/nova/api/openstack/compute/plugins/v3/hypervisors.py
+++ b/nova/api/openstack/compute/plugins/v3/hypervisors.py
@@ -21,6 +21,7 @@ from nova.api.openstack import extensions
from nova import compute
from nova import exception
from nova.i18n import _
+from nova import servicegroup
ALIAS = "os-hypervisors"
@@ -32,12 +33,17 @@ class HypervisorsController(object):
def __init__(self):
self.host_api = compute.HostAPI()
+ self.servicegroup_api = servicegroup.API()
super(HypervisorsController, self).__init__()
def _view_hypervisor(self, hypervisor, detail, servers=None, **kwargs):
+ alive = self.servicegroup_api.service_is_up(hypervisor['service'])
hyp_dict = {
'id': hypervisor['id'],
'hypervisor_hostname': hypervisor['hypervisor_hostname'],
+ 'state': 'up' if alive else 'down',
+ 'status': ('disabled' if hypervisor['service']['disabled']
+ else 'enabled'),
}
if detail and not servers:
@@ -52,6 +58,7 @@ class HypervisorsController(object):
hyp_dict['service'] = {
'id': hypervisor['service_id'],
'host': hypervisor['service']['host'],
+ 'disabled_reason': hypervisor['service']['disabled_reason'],
}
if servers is not None:
diff --git a/nova/tests/api/openstack/compute/contrib/test_hypervisor_status.py b/nova/tests/api/openstack/compute/contrib/test_hypervisor_status.py
new file mode 100644
index 000000000000..1d8cd95358c6
--- /dev/null
+++ b/nova/tests/api/openstack/compute/contrib/test_hypervisor_status.py
@@ -0,0 +1,80 @@
+# Copyright 2014 Intel Corp.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import copy
+
+import mock
+
+from nova.api.openstack.compute.contrib import hypervisors
+from nova.tests.api.openstack.compute.contrib import test_hypervisors
+
+
+TEST_HYPER = dict(test_hypervisors.TEST_HYPERS[0],
+ service=dict(id=1,
+ host="compute1",
+ binary="nova-compute",
+ topic="compute_topic",
+ report_count=5,
+ disabled=False,
+ disabled_reason=None,
+ availability_zone="nova"),
+ )
+
+
+class HypervisorStatusTest(test_hypervisors.HypervisorsTest):
+ def _prepare_extension(self):
+ self.ext_mgr.extensions['os-hypervisor-status'] = True
+ self.controller = hypervisors.HypervisorsController(self.ext_mgr)
+ self.controller.servicegroup_api.service_is_up = mock.MagicMock(
+ return_value=True)
+
+ def test_view_hypervisor_service_status(self):
+ self._prepare_extension()
+ result = self.controller._view_hypervisor(
+ TEST_HYPER, False)
+ self.assertEqual('enabled', result['status'])
+ self.assertEqual('up', result['state'])
+ self.assertEqual('enabled', result['status'])
+
+ self.controller.servicegroup_api.service_is_up.return_value = False
+ result = self.controller._view_hypervisor(
+ TEST_HYPER, False)
+ self.assertEqual('down', result['state'])
+
+ hyper = copy.deepcopy(TEST_HYPER)
+ hyper['service']['disabled'] = True
+ result = self.controller._view_hypervisor(hyper, False)
+ self.assertEqual('disabled', result['status'])
+
+ def test_view_hypervisor_detail_status(self):
+ self._prepare_extension()
+
+ result = self.controller._view_hypervisor(
+ TEST_HYPER, True)
+
+ self.assertEqual('enabled', result['status'])
+ self.assertEqual('up', result['state'])
+ self.assertIsNone(result['service']['disabled_reason'])
+
+ self.controller.servicegroup_api.service_is_up.return_value = False
+ result = self.controller._view_hypervisor(
+ TEST_HYPER, True)
+ self.assertEqual('down', result['state'])
+
+ hyper = copy.deepcopy(TEST_HYPER)
+ hyper['service']['disabled'] = True
+ hyper['service']['disabled_reason'] = "fake"
+ result = self.controller._view_hypervisor(hyper, True)
+ self.assertEqual('disabled', result['status'],)
+ self.assertEqual('fake', result['service']['disabled_reason'])
diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_hypervisors.py b/nova/tests/api/openstack/compute/plugins/v3/test_hypervisors.py
index 7d746c8148d8..039dae759c97 100644
--- a/nova/tests/api/openstack/compute/plugins/v3/test_hypervisors.py
+++ b/nova/tests/api/openstack/compute/plugins/v3/test_hypervisors.py
@@ -13,6 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+import copy
+
+import mock
from webob import exc
from nova.api.openstack.compute.plugins.v3 import hypervisors
@@ -32,6 +35,7 @@ TEST_HYPERS = [
topic="compute_topic",
report_count=5,
disabled=False,
+ disabled_reason=None,
availability_zone="nova"),
vcpus=4,
memory_mb=10 * 1024,
@@ -57,6 +61,7 @@ TEST_HYPERS = [
topic="compute_topic",
report_count=5,
disabled=False,
+ disabled_reason=None,
availability_zone="nova"),
vcpus=4,
memory_mb=10 * 1024,
@@ -134,6 +139,8 @@ class HypervisorsTest(test.NoDBTestCase):
def setUp(self):
super(HypervisorsTest, self).setUp()
self.controller = hypervisors.HypervisorsController()
+ self.controller.servicegroup_api.service_is_up = mock.MagicMock(
+ return_value=True)
self.stubs.Set(db, 'compute_node_get_all', fake_compute_node_get_all)
self.stubs.Set(db, 'compute_node_search_by_hypervisor',
@@ -148,7 +155,9 @@ class HypervisorsTest(test.NoDBTestCase):
def test_view_hypervisor_nodetail_noservers(self):
result = self.controller._view_hypervisor(TEST_HYPERS[0], False)
- self.assertEqual(result, dict(id=1, hypervisor_hostname="hyper1"))
+ self.assertEqual(dict(id=1, hypervisor_hostname="hyper1",
+ state='up', status='enabled'),
+ result)
def test_view_hypervisor_detail_noservers(self):
result = self.controller._view_hypervisor(TEST_HYPERS[0], True)
@@ -156,6 +165,8 @@ class HypervisorsTest(test.NoDBTestCase):
self.assertEqual(result, dict(
id=1,
hypervisor_hostname="hyper1",
+ state='up',
+ status='enabled',
vcpus=4,
memory_mb=10 * 1024,
local_gb=250,
@@ -171,7 +182,7 @@ class HypervisorsTest(test.NoDBTestCase):
cpu_info='cpu_info',
disk_available_least=100,
host_ip='1.1.1.1',
- service=dict(id=1, host='compute1')))
+ service=dict(id=1, host='compute1', disabled_reason=None)))
def test_view_hypervisor_servers(self):
result = self.controller._view_hypervisor(TEST_HYPERS[0], False,
@@ -180,20 +191,44 @@ class HypervisorsTest(test.NoDBTestCase):
self.assertEqual(result, dict(
id=1,
hypervisor_hostname="hyper1",
+ state='up',
+ status='enabled',
servers=[
dict(name="inst1", id="uuid1"),
dict(name="inst2", id="uuid2"),
dict(name="inst3", id="uuid3"),
dict(name="inst4", id="uuid4")]))
+ def test_view_hypervisor_service_status(self):
+ result = self.controller._view_hypervisor(TEST_HYPERS[0], False)
+ self.assertEqual('up', result['state'])
+ self.assertEqual('enabled', result['status'])
+
+ self.controller.servicegroup_api.service_is_up.return_value = False
+ result = self.controller._view_hypervisor(TEST_HYPERS[0], False)
+ self.assertEqual('down', result['state'])
+ self.assertEqual('enabled', result['status'])
+
+ hyper = copy.deepcopy(TEST_HYPERS[0])
+ hyper['service']['disabled'] = True
+ result = self.controller._view_hypervisor(hyper, False)
+ self.assertEqual('down', result['state'])
+ self.assertEqual('disabled', result['status'])
+
def test_index(self):
req = fakes.HTTPRequestV3.blank('/os-hypervisors',
use_admin_context=True)
result = self.controller.index(req)
self.assertEqual(result, dict(hypervisors=[
- dict(id=1, hypervisor_hostname="hyper1"),
- dict(id=2, hypervisor_hostname="hyper2")]))
+ dict(id=1,
+ hypervisor_hostname="hyper1",
+ state='up',
+ status='enabled'),
+ dict(id=2,
+ hypervisor_hostname="hyper2",
+ state='up',
+ status='enabled')]))
def test_index_non_admin(self):
req = fakes.HTTPRequestV3.blank('/os-hypervisors')
@@ -207,8 +242,11 @@ class HypervisorsTest(test.NoDBTestCase):
self.assertEqual(result, dict(hypervisors=[
dict(id=1,
- service=dict(id=1, host="compute1"),
+ service=dict(
+ id=1, host="compute1", disabled_reason=None),
vcpus=4,
+ state='up',
+ status='enabled',
memory_mb=10 * 1024,
local_gb=250,
vcpus_used=2,
@@ -225,8 +263,11 @@ class HypervisorsTest(test.NoDBTestCase):
disk_available_least=100,
host_ip='1.1.1.1'),
dict(id=2,
- service=dict(id=2, host="compute2"),
+ service=dict(id=2, host="compute2",
+ disabled_reason=None),
vcpus=4,
+ state='up',
+ status='enabled',
memory_mb=10 * 1024,
local_gb=250,
vcpus_used=2,
@@ -265,8 +306,10 @@ class HypervisorsTest(test.NoDBTestCase):
self.assertEqual(result, dict(hypervisor=dict(
id=1,
- service=dict(id=1, host="compute1"),
+ service=dict(id=1, host="compute1", disabled_reason=None),
vcpus=4,
+ state='up',
+ status='enabled',
memory_mb=10 * 1024,
local_gb=250,
vcpus_used=2,
@@ -319,6 +362,8 @@ class HypervisorsTest(test.NoDBTestCase):
self.assertEqual(result, dict(hypervisor=dict(
id=1,
hypervisor_hostname="hyper1",
+ state='up',
+ status='enabled',
uptime="fake uptime")))
def test_uptime_non_integer_id(self):
@@ -336,8 +381,10 @@ class HypervisorsTest(test.NoDBTestCase):
use_admin_context=True)
result = self.controller.search(req)
self.assertEqual(result, dict(hypervisors=[
- dict(id=1, hypervisor_hostname="hyper1"),
- dict(id=2, hypervisor_hostname="hyper2")]))
+ dict(id=1, hypervisor_hostname="hyper1",
+ state='up', status='enabled'),
+ dict(id=2, hypervisor_hostname="hyper2",
+ state='up', status='enabled')]))
def test_search_non_exist(self):
def fake_compute_node_search_by_hypervisor_return_empty(context,
@@ -362,6 +409,8 @@ class HypervisorsTest(test.NoDBTestCase):
self.assertEqual(result, dict(hypervisor=
dict(id=1,
hypervisor_hostname="hyper1",
+ state='up',
+ status='enabled',
servers=[
dict(name="inst1", id="uuid1"),
dict(name="inst3", id="uuid3")])))
@@ -387,6 +436,8 @@ class HypervisorsTest(test.NoDBTestCase):
self.assertEqual(result, dict(hypervisor=
dict(id=1,
hypervisor_hostname="hyper1",
+ state='up',
+ status='enabled',
servers=[])))
def test_servers_with_non_integer_hypervisor_id(self):
diff --git a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl
index ac203b83d4ea..6a243b5af4fb 100644
--- a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl
+++ b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl
@@ -416,6 +416,14 @@
"namespace": "http://docs.openstack.org/compute/ext/extended_hypervisors/api/v1.1",
"updated": "%(isotime)s"
},
+ {
+ "alias": "os-hypervisor-status",
+ "description": "%(text)s",
+ "links": [],
+ "name": "HypervisorStatus",
+ "namespace": "http://docs.openstack.org/compute/ext/hypervisor_status/api/v1.1",
+ "updated": "%(isotime)s"
+ },
{
"alias": "os-server-external-events",
"description": "%(text)s",
diff --git a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl
index 308d32136bdd..3e5ac8ea27f4 100644
--- a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl
+++ b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl
@@ -150,6 +150,9 @@
%(text)s
+
+ %(text)s
+
%(text)s
diff --git a/nova/tests/integrated/api_samples/os-hypervisor-status/hypervisors-show-with-status-resp.json.tpl b/nova/tests/integrated/api_samples/os-hypervisor-status/hypervisors-show-with-status-resp.json.tpl
new file mode 100644
index 000000000000..14464ccf4d06
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-hypervisor-status/hypervisors-show-with-status-resp.json.tpl
@@ -0,0 +1,27 @@
+{
+ "hypervisor": {
+ "cpu_info": "?",
+ "current_workload": 0,
+ "disk_available_least": 0,
+ "free_disk_gb": 1028,
+ "free_ram_mb": 7680,
+ "hypervisor_hostname": "fake-mini",
+ "hypervisor_type": "fake",
+ "hypervisor_version": 1000,
+ "id": %(hypervisor_id)s,
+ "local_gb": 1028,
+ "local_gb_used": 0,
+ "memory_mb": 8192,
+ "memory_mb_used": 512,
+ "running_vms": 0,
+ "state": "up",
+ "status": "enabled",
+ "service": {
+ "host": "%(host_name)s",
+ "id": 2,
+ "disabled_reason": null
+ },
+ "vcpus": 1,
+ "vcpus_used": 0
+ }
+}
diff --git a/nova/tests/integrated/api_samples/os-hypervisor-status/hypervisors-show-with-status-resp.xml.tpl b/nova/tests/integrated/api_samples/os-hypervisor-status/hypervisors-show-with-status-resp.xml.tpl
new file mode 100644
index 000000000000..6cfd860af530
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-hypervisor-status/hypervisors-show-with-status-resp.xml.tpl
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/nova/tests/integrated/test_api_samples.py b/nova/tests/integrated/test_api_samples.py
index 0d7dc6311183..fedcee8fe081 100644
--- a/nova/tests/integrated/test_api_samples.py
+++ b/nova/tests/integrated/test_api_samples.py
@@ -1771,7 +1771,7 @@ class ServicesJsonTest(ApiSampleTestBaseV2):
'status': 'disabled',
'state': 'up'}
subs.update(self._get_regexes())
- return self._verify_response('services-get-resp',
+ self._verify_response('services-get-resp',
subs, response, 200)
def test_service_disable_log_reason(self):
@@ -3584,6 +3584,12 @@ class HypervisorsSampleJsonTests(ApiSampleTestBaseV2):
extension_name = ("nova.api.openstack.compute.contrib.hypervisors."
"Hypervisors")
+ def setUp(self):
+ super(HypervisorsSampleJsonTests, self).setUp()
+ mock.patch("nova.servicegroup.API.service_is_up",
+ return_value=True).start()
+ self.addCleanup(mock.patch.stopall)
+
def test_hypervisors_list(self):
response = self._do_get('os-hypervisors')
self._verify_response('hypervisors-list-resp', {}, response, 200)
@@ -3646,9 +3652,31 @@ class ExtendedHypervisorsJsonTest(ApiSampleTestBaseV2):
class ExtendedHypervisorsXmlTest(ExtendedHypervisorsJsonTest):
+ ctype = "xml"
+
+
+class HypervisorStatusJsonTest(ApiSampleTestBaseV2):
+ extends_name = ("nova.api.openstack.compute.contrib."
+ "hypervisors.Hypervisors")
+ extension_name = ("nova.api.openstack.compute.contrib."
+ "hypervisor_status.Hypervisor_status")
+
+ def test_hypervisors_show_with_status(self):
+ hypervisor_id = 1
+ subs = {
+ 'hypervisor_id': hypervisor_id
+ }
+ response = self._do_get('os-hypervisors/%s' % hypervisor_id)
+ subs.update(self._get_regexes())
+ self._verify_response('hypervisors-show-with-status-resp',
+ subs, response, 200)
+
+
+class HypervisorStatusXmlTest(HypervisorStatusJsonTest):
ctype = 'xml'
+@mock.patch("nova.servicegroup.API.service_is_up", return_value=True)
class HypervisorsCellsSampleJsonTests(ApiSampleTestBaseV2):
extension_name = ("nova.api.openstack.compute.contrib.hypervisors."
"Hypervisors")
@@ -3657,9 +3685,11 @@ class HypervisorsCellsSampleJsonTests(ApiSampleTestBaseV2):
self.flags(enable=True, cell_type='api', group='cells')
super(HypervisorsCellsSampleJsonTests, self).setUp()
- def test_hypervisor_uptime(self):
- fake_hypervisor = {'service': {'host': 'fake-mini'}, 'id': 1,
- 'hypervisor_hostname': 'fake-mini'}
+ def test_hypervisor_uptime(self, mocks):
+ fake_hypervisor = {'service': {'host': 'fake-mini',
+ 'disabled': False,
+ 'disabled_reason': None},
+ 'id': 1, 'hypervisor_hostname': 'fake-mini'}
def fake_get_host_uptime(self, context, hyp):
return (" 08:32:11 up 93 days, 18:25, 12 users, load average:"
diff --git a/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-detail-resp.json.tpl b/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-detail-resp.json.tpl
index fb473a03bbcb..2777eb488740 100644
--- a/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-detail-resp.json.tpl
+++ b/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-detail-resp.json.tpl
@@ -3,6 +3,8 @@
{
"cpu_info": "?",
"current_workload": 0,
+ "state": "up",
+ "status": "enabled",
"disk_available_least": 0,
"host_ip": "%(ip)s",
"free_disk_gb": 1028,
@@ -18,7 +20,8 @@
"running_vms": 0,
"service": {
"host": "%(host_name)s",
- "id": 2
+ "id": 2,
+ "disabled_reason": null
},
"vcpus": 1,
"vcpus_used": 0
diff --git a/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-list-resp.json.tpl b/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-list-resp.json.tpl
index 8d94021274fb..710cdfcf9cb0 100644
--- a/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-list-resp.json.tpl
+++ b/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-list-resp.json.tpl
@@ -2,7 +2,9 @@
"hypervisors": [
{
"hypervisor_hostname": "fake-mini",
+ "state": "up",
+ "status": "enabled",
"id": 1
}
]
-}
\ No newline at end of file
+}
diff --git a/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-search-resp.json.tpl b/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-search-resp.json.tpl
index 8d94021274fb..375627499df6 100644
--- a/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-search-resp.json.tpl
+++ b/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-search-resp.json.tpl
@@ -2,7 +2,9 @@
"hypervisors": [
{
"hypervisor_hostname": "fake-mini",
- "id": 1
+ "id": 1,
+ "state": "up",
+ "status": "enabled"
}
]
-}
\ No newline at end of file
+}
diff --git a/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-servers-resp.json.tpl b/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-servers-resp.json.tpl
index 934ef0c02db7..710b05b9309a 100644
--- a/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-servers-resp.json.tpl
+++ b/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-servers-resp.json.tpl
@@ -2,6 +2,8 @@
"hypervisor": {
"hypervisor_hostname": "fake-mini",
"id": 1,
+ "state": "up",
+ "status": "enabled",
"servers": []
}
-}
\ No newline at end of file
+}
diff --git a/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-show-resp.json.tpl b/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-show-resp.json.tpl
index a1e5f2080b45..f125da01af9f 100644
--- a/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-show-resp.json.tpl
+++ b/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-show-resp.json.tpl
@@ -3,6 +3,8 @@
"cpu_info": "?",
"current_workload": 0,
"disk_available_least": 0,
+ "state": "up",
+ "status": "enabled",
"host_ip": "%(ip)s",
"free_disk_gb": 1028,
"free_ram_mb": 7680,
@@ -17,7 +19,8 @@
"running_vms": 0,
"service": {
"host": "%(host_name)s",
- "id": 2
+ "id": 2,
+ "disabled_reason": null
},
"vcpus": 1,
"vcpus_used": 0
diff --git a/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-uptime-resp.json.tpl b/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-uptime-resp.json.tpl
index 8a36c65f232a..e2f6d2e47e74 100644
--- a/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-uptime-resp.json.tpl
+++ b/nova/tests/integrated/v3/api_samples/os-hypervisors/hypervisors-uptime-resp.json.tpl
@@ -2,6 +2,8 @@
"hypervisor": {
"hypervisor_hostname": "fake-mini",
"id": %(hypervisor_id)s,
+ "state": "up",
+ "status": "enabled",
"uptime": " 08:32:11 up 93 days, 18:25, 12 users, load average: 0.20, 0.12, 0.14"
}
}
diff --git a/nova/tests/integrated/v3/api_samples/os-pci/hypervisors-pci-detail-resp.json.tpl b/nova/tests/integrated/v3/api_samples/os-pci/hypervisors-pci-detail-resp.json.tpl
index 69c5df943fa2..f2bf2bc02c84 100644
--- a/nova/tests/integrated/v3/api_samples/os-pci/hypervisors-pci-detail-resp.json.tpl
+++ b/nova/tests/integrated/v3/api_samples/os-pci/hypervisors-pci-detail-resp.json.tpl
@@ -2,6 +2,8 @@
"hypervisors": [
{
"cpu_info": "?",
+ "state": "up",
+ "status": "enabled",
"current_workload": 0,
"disk_available_least": 0,
"host_ip": "%(ip)s",
@@ -30,7 +32,8 @@
"running_vms": 0,
"service": {
"host": "043b3cacf6f34c90a7245151fc8ebcda",
- "id": 2
+ "id": 2,
+ "disabled_reason": null
},
"vcpus": 1,
"vcpus_used": 0
diff --git a/nova/tests/integrated/v3/api_samples/os-pci/hypervisors-pci-show-resp.json.tpl b/nova/tests/integrated/v3/api_samples/os-pci/hypervisors-pci-show-resp.json.tpl
index 6a6fbe3d3b47..3c0fc0abcd78 100644
--- a/nova/tests/integrated/v3/api_samples/os-pci/hypervisors-pci-show-resp.json.tpl
+++ b/nova/tests/integrated/v3/api_samples/os-pci/hypervisors-pci-show-resp.json.tpl
@@ -2,6 +2,8 @@
"hypervisor": {
"cpu_info": "?",
"current_workload": 0,
+ "state": "up",
+ "status": "enabled",
"disk_available_least": 0,
"host_ip": "%(ip)s",
"free_disk_gb": 1028,
@@ -29,7 +31,8 @@
"running_vms": 0,
"service": {
"host": "043b3cacf6f34c90a7245151fc8ebcda",
- "id": 2
+ "id": 2,
+ "disabled_reason": null
},
"vcpus": 1,
"vcpus_used": 0
diff --git a/nova/tests/integrated/v3/test_pci.py b/nova/tests/integrated/v3/test_pci.py
index 30c664dbf2fd..91aba3f9c7df 100644
--- a/nova/tests/integrated/v3/test_pci.py
+++ b/nova/tests/integrated/v3/test_pci.py
@@ -12,6 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import mock
+
from nova import db
from nova.openstack.common import jsonutils
from nova.tests.integrated.v3 import api_sample_base
@@ -83,6 +85,8 @@ class ExtendedHyervisorPciSampleJsonTest(api_sample_base.ApiSampleTestBaseV3):
"current_workload": 0,
"disk_available_least": 0,
"host_ip": "1.1.1.1",
+ "state": "up",
+ "status": "enabled",
"free_disk_gb": 1028,
"free_ram_mb": 7680,
"hypervisor_hostname": "fake-mini",
@@ -94,8 +98,10 @@ class ExtendedHyervisorPciSampleJsonTest(api_sample_base.ApiSampleTestBaseV3):
"memory_mb": 8192,
"memory_mb_used": 512,
"running_vms": 0,
- "service": {"host": '043b3cacf6f34c90a724'
- '5151fc8ebcda'},
+ "service": {"host": '043b3cacf6f34c90a'
+ '7245151fc8ebcda',
+ "disabled": False,
+ "disabled_reason": None},
"vcpus": 1,
"vcpus_used": 0,
"service_id": 2,
@@ -110,13 +116,12 @@ class ExtendedHyervisorPciSampleJsonTest(api_sample_base.ApiSampleTestBaseV3):
' "0x1"]]',
"key1": "value1"}}]}
- def test_pci_show(self):
- def fake_compute_node_get(context, id):
- self.fake_compute_node['pci_stats'] = jsonutils.dumps(
- self.fake_compute_node['pci_stats'])
- return self.fake_compute_node
-
- self.stubs.Set(db, 'compute_node_get', fake_compute_node_get)
+ @mock.patch("nova.servicegroup.API.service_is_up", return_value=True)
+ @mock.patch("nova.db.compute_node_get")
+ def test_pci_show(self, mock_db, mock_service):
+ self.fake_compute_node['pci_stats'] = jsonutils.dumps(
+ self.fake_compute_node['pci_stats'])
+ mock_db.return_value = self.fake_compute_node
hypervisor_id = 1
response = self._do_get('os-hypervisors/%s' % hypervisor_id)
subs = {
@@ -126,13 +131,13 @@ class ExtendedHyervisorPciSampleJsonTest(api_sample_base.ApiSampleTestBaseV3):
self._verify_response('hypervisors-pci-show-resp',
subs, response, 200)
- def test_pci_detail(self):
- def fake_compute_node_get_all(context):
- self.fake_compute_node['pci_stats'] = jsonutils.dumps(
- self.fake_compute_node['pci_stats'])
- return [self.fake_compute_node]
+ @mock.patch("nova.servicegroup.API.service_is_up", return_value=True)
+ @mock.patch("nova.db.compute_node_get_all")
+ def test_pci_detail(self, mock_db, mock_service):
+ self.fake_compute_node['pci_stats'] = jsonutils.dumps(
+ self.fake_compute_node['pci_stats'])
- self.stubs.Set(db, 'compute_node_get_all', fake_compute_node_get_all)
+ mock_db.return_value = [self.fake_compute_node]
hypervisor_id = 1
subs = {
'hypervisor_id': hypervisor_id