nova/nova/tests/functional/api_sample_tests/test_hypervisors.py
Eric Fried 112cd9cd1f Proper error handling by _ensure_resource_provider
Previously, if _ensure_resource_provider encountered any error from the
placement REST API, it would (sometimes log a message and) return None.

Furthermore, a name conflict while creating the provider was treated the
same as a UUID conflict, which would actually result in None being
returned.

With this change set, the error paths that previously returned None now
raise one of the new ResourceProviderRetrievalFailed or
ResourceProviderCreationFailed exceptions; and the name conflict path is
detected and treated as an error condition.

Note: This change set only touches the SchedulerReportClient side of
these error conditions - it makes no attempt to add error handling to
its callers.  Case in point, the API samples tests needed fixing because
they were previously running into the name conflict error condition, but
not noticing.  As currently implemented, the new exceptions will
percolate up to ComputeManager.update_available_resource_for_node like
any others coming from SchedulerReportClient, where they will be logged
and ignored.

Change-Id: I0c4ca6a81f213277fe7219cb905a805712f81e36
Closes-Bug: #1735430
2017-11-30 18:30:49 +00:00

323 lines
13 KiB
Python

# Copyright 2012 Nebula, Inc.
# Copyright 2013 IBM 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 mock
from nova.cells import utils as cells_utils
from nova import objects
from nova.tests.functional.api_sample_tests import api_sample_base
from nova.virt import fake
class HypervisorsSampleJsonTests(api_sample_base.ApiSampleTestBaseV21):
ADMIN_API = True
sample_dir = "os-hypervisors"
def test_hypervisors_list(self):
response = self._do_get('os-hypervisors')
self._verify_response('hypervisors-list-resp', {}, response, 200)
def test_hypervisors_search(self):
response = self._do_get('os-hypervisors/fake/search')
self._verify_response('hypervisors-search-resp', {}, response, 200)
def test_hypervisors_without_servers(self):
response = self._do_get('os-hypervisors/fake/servers')
self._verify_response('hypervisors-without-servers-resp',
{}, response, 200)
@mock.patch("nova.compute.api.HostAPI.instance_get_all_by_host")
def test_hypervisors_with_servers(self, mock_instance_get):
instance = [
{
"deleted": None,
"name": "test_server1",
"uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
},
{
"deleted": None,
"name": "test_server2",
"uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"
}]
mock_instance_get.return_value = instance
response = self._do_get('os-hypervisors/fake/servers')
self._verify_response('hypervisors-with-servers-resp', {},
response, 200)
def test_hypervisors_detail(self):
hypervisor_id = '1'
subs = {
'hypervisor_id': hypervisor_id,
'service_id': '[0-9]+',
}
response = self._do_get('os-hypervisors/detail')
self._verify_response('hypervisors-detail-resp', subs, response, 200)
def test_hypervisors_show(self):
hypervisor_id = '1'
subs = {
'hypervisor_id': hypervisor_id,
'service_id': '[0-9]+',
}
response = self._do_get('os-hypervisors/%s' % hypervisor_id)
self._verify_response('hypervisors-show-resp', subs, response, 200)
def test_hypervisors_statistics(self):
response = self._do_get('os-hypervisors/statistics')
self._verify_response('hypervisors-statistics-resp', {}, response, 200)
def test_hypervisors_uptime(self):
def fake_get_host_uptime(self, context, hyp):
return (" 08:32:11 up 93 days, 18:25, 12 users, load average:"
" 0.20, 0.12, 0.14")
self.stub_out('nova.compute.api.HostAPI.get_host_uptime',
fake_get_host_uptime)
hypervisor_id = '1'
response = self._do_get('os-hypervisors/%s/uptime' % hypervisor_id)
subs = {
'hypervisor_id': hypervisor_id,
}
self._verify_response('hypervisors-uptime-resp', subs, response, 200)
@mock.patch("nova.servicegroup.API.service_is_up", return_value=True)
class HypervisorsCellsSampleJsonTests(api_sample_base.ApiSampleTestBaseV21):
ADMIN_API = True
sample_dir = "os-hypervisors"
def setUp(self):
self.flags(enable=True, cell_type='api', group='cells')
super(HypervisorsCellsSampleJsonTests, self).setUp()
def test_hypervisor_uptime(self, mocks):
fake_hypervisor = objects.ComputeNode(id=1, host='fake-mini',
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:"
" 0.20, 0.12, 0.14")
def fake_compute_node_get(self, context, hyp):
return fake_hypervisor
def fake_service_get_by_compute_host(self, context, host):
return cells_utils.ServiceProxy(
objects.Service(id=1, host='fake-mini', disabled=False,
disabled_reason=None),
'cell1')
self.stub_out(
'nova.compute.cells_api.HostAPI.compute_node_get',
fake_compute_node_get)
self.stub_out(
'nova.compute.cells_api.HostAPI.service_get_by_compute_host',
fake_service_get_by_compute_host)
self.stub_out(
'nova.compute.cells_api.HostAPI.get_host_uptime',
fake_get_host_uptime)
hypervisor_id = fake_hypervisor.id
response = self._do_get('os-hypervisors/%s/uptime' % hypervisor_id)
subs = {'hypervisor_id': str(hypervisor_id)}
self._verify_response('hypervisors-uptime-resp', subs, response, 200)
class HypervisorsSampleJson228Tests(HypervisorsSampleJsonTests):
microversion = '2.28'
scenarios = [('v2_28', {'api_major_version': 'v2.1'})]
def setUp(self):
super(HypervisorsSampleJson228Tests, self).setUp()
self.api.microversion = self.microversion
class HypervisorsSampleJson233Tests(api_sample_base.ApiSampleTestBaseV21):
ADMIN_API = True
sample_dir = "os-hypervisors"
microversion = '2.33'
scenarios = [('v2_33', {'api_major_version': 'v2.1'})]
def setUp(self):
super(HypervisorsSampleJson233Tests, self).setUp()
self.api.microversion = self.microversion
# Start a new compute service to fake a record with hypervisor id=2
# for pagination test.
host = 'host1'
fake.set_nodes([host])
self.addCleanup(fake.restore_nodes)
self.start_service('compute', host=host)
def test_hypervisors_list(self):
response = self._do_get('os-hypervisors?limit=1&marker=1')
self._verify_response('hypervisors-list-resp', {}, response, 200)
def test_hypervisors_detail(self):
subs = {
'hypervisor_id': '2',
'host': 'host1',
'host_name': 'host1'
}
response = self._do_get('os-hypervisors/detail?limit=1&marker=1')
self._verify_response('hypervisors-detail-resp', subs, response, 200)
class HypervisorsSampleJson253Tests(HypervisorsSampleJson228Tests):
microversion = '2.53'
scenarios = [('v2_53', {'api_major_version': 'v2.1'})]
def setUp(self):
super(HypervisorsSampleJson253Tests, self).setUp()
self.compute_node_1 = self.compute.service_ref.compute_node
def generalize_subs(self, subs, vanilla_regexes):
"""Give the test a chance to modify subs after the server response
was verified, and before the on-disk doc/api_samples file is checked.
"""
# When comparing the template to the sample we just care that the
# hypervisor id and service id are UUIDs.
subs['hypervisor_id'] = vanilla_regexes['uuid']
subs['service_id'] = vanilla_regexes['uuid']
return subs
def test_hypervisors_list(self):
# Start another compute service to get a 2nd compute for paging tests.
compute_node_2 = self.start_service(
'compute', host='host2').service_ref.compute_node
marker = self.compute_node_1.uuid
response = self._do_get('os-hypervisors?limit=1&marker=%s' % marker)
subs = {'hypervisor_id': compute_node_2.uuid}
self._verify_response('hypervisors-list-resp', subs, response, 200)
def test_hypervisors_detail(self):
# Start another compute service to get a 2nd compute for paging tests.
host = 'host2'
fake.set_nodes([host])
self.addCleanup(fake.restore_nodes)
service_2 = self.start_service('compute', host=host).service_ref
compute_node_2 = service_2.compute_node
marker = self.compute_node_1.uuid
subs = {
'hypervisor_id': compute_node_2.uuid,
'service_id': service_2.uuid
}
response = self._do_get('os-hypervisors/detail?limit=1&marker=%s' %
marker)
self._verify_response('hypervisors-detail-resp', subs, response, 200)
@mock.patch("nova.compute.api.HostAPI.instance_get_all_by_host")
def test_hypervisors_detail_with_servers(self, instance_get_all_by_host):
"""List hypervisors with details and with hosted servers."""
instances = [
{
"name": "test_server1",
"uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
},
{
"name": "test_server2",
"uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"
}]
instance_get_all_by_host.return_value = instances
response = self._do_get('os-hypervisors/detail?with_servers=1')
subs = {
'hypervisor_id': self.compute_node_1.uuid,
'service_id': self.compute.service_ref.uuid,
}
self._verify_response('hypervisors-detail-with-servers-resp',
subs, response, 200)
def test_hypervisors_search(self):
"""The search route is deprecated in 2.53 and is now a query parameter
on the GET /os-hypervisors API.
"""
response = self._do_get(
'os-hypervisors?hypervisor_hostname_pattern=fake')
subs = {'hypervisor_id': self.compute_node_1.uuid}
self._verify_response('hypervisors-search-resp', subs, response, 200)
@mock.patch("nova.compute.api.HostAPI.instance_get_all_by_host")
def test_hypervisors_with_servers(self, instance_get_all_by_host):
"""The servers route is deprecated in 2.53 and is now a query parameter
on the GET /os-hypervisors API.
"""
instances = [
{
"name": "test_server1",
"uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
},
{
"name": "test_server2",
"uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"
}]
instance_get_all_by_host.return_value = instances
response = self._do_get('os-hypervisors?with_servers=true')
subs = {'hypervisor_id': self.compute_node_1.uuid}
self._verify_response('hypervisors-with-servers-resp', subs,
response, 200)
def test_hypervisors_without_servers(self):
# This is the same as GET /os-hypervisors in 2.53 which is covered by
# test_hypervisors_list already.
pass
def test_hypervisors_uptime(self):
def fake_get_host_uptime(self, context, hyp):
return (" 08:32:11 up 93 days, 18:25, 12 users, load average:"
" 0.20, 0.12, 0.14")
self.stub_out('nova.compute.api.HostAPI.get_host_uptime',
fake_get_host_uptime)
hypervisor_id = self.compute_node_1.uuid
response = self._do_get('os-hypervisors/%s/uptime' % hypervisor_id)
subs = {
'hypervisor_id': hypervisor_id,
}
self._verify_response('hypervisors-uptime-resp', subs, response, 200)
def test_hypervisors_show(self):
hypervisor_id = self.compute_node_1.uuid
subs = {
'hypervisor_id': hypervisor_id,
'service_id': self.compute.service_ref.uuid,
}
response = self._do_get('os-hypervisors/%s' % hypervisor_id)
self._verify_response('hypervisors-show-resp', subs, response, 200)
@mock.patch("nova.compute.api.HostAPI.instance_get_all_by_host")
def test_hypervisors_show_with_servers(self, instance_get_all_by_host):
"""Tests getting details for a specific hypervisor and including the
hosted servers in the response.
"""
instances = [
{
"name": "test_server1",
"uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
},
{
"name": "test_server2",
"uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"
}]
instance_get_all_by_host.return_value = instances
hypervisor_id = self.compute_node_1.uuid
subs = {
'hypervisor_id': hypervisor_id,
'service_id': self.compute.service_ref.uuid,
}
response = self._do_get('os-hypervisors/%s?with_servers=1' %
hypervisor_id)
self._verify_response('hypervisors-show-with-servers-resp', subs,
response, 200)