Enforce case-sensitive hostnames in aggregate host add
If we are using a case-insensitive backend database like mysql, a
user can request an aggregate host add with a non-matching hostname
and we will not signal failure. We will create a mapping which will
not actually include that host in the aggregate, which will be
confusing later. This change makes us fail if the host name does not
match exactly, which is the same behavior as if we are using a
case-sensitive backend (like postgres).
Change-Id: I597dee74d33de337913eddda74ab056fbf81a23c
Closes-Bug: #1709260
(cherry picked from commit c8e2de6684
)
This commit is contained in:
parent
c8ea8ed466
commit
c72bb2c747
|
@ -5325,14 +5325,23 @@ class AggregateAPI(base.Base):
|
|||
try:
|
||||
mapping = objects.HostMapping.get_by_host(context, host_name)
|
||||
nova_context.set_target_cell(context, mapping.cell_mapping)
|
||||
objects.Service.get_by_compute_host(context, host_name)
|
||||
service = objects.Service.get_by_compute_host(context, host_name)
|
||||
except exception.HostMappingNotFound:
|
||||
try:
|
||||
# NOTE(danms): This targets our cell
|
||||
_find_service_in_cell(context, service_host=host_name)
|
||||
service = _find_service_in_cell(context,
|
||||
service_host=host_name)
|
||||
except exception.NotFound:
|
||||
raise exception.ComputeHostNotFound(host=host_name)
|
||||
|
||||
if service.host != host_name:
|
||||
# NOTE(danms): If we found a service but it is not an
|
||||
# exact match, we may have a case-insensitive backend
|
||||
# database (like mysql) which will end up with us
|
||||
# adding the host-aggregate mapping with a
|
||||
# non-matching hostname.
|
||||
raise exception.ComputeHostNotFound(host=host_name)
|
||||
|
||||
aggregate = objects.Aggregate.get_by_id(context, aggregate_id)
|
||||
|
||||
compute_utils.notify_about_aggregate_action(
|
||||
|
|
|
@ -12086,6 +12086,29 @@ class ComputeAPIAggrTestCase(BaseTestCase):
|
|||
'compute.fake-mini')
|
||||
mock_add_host.assert_not_called()
|
||||
|
||||
@mock.patch('nova.objects.Service.get_by_compute_host')
|
||||
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.'
|
||||
'aggregate_add_host')
|
||||
def test_add_host_to_aggregate_raise_not_found_case(self, mock_add_host,
|
||||
mock_get_service):
|
||||
# Ensure ComputeHostNotFound is raised when adding a host with a
|
||||
# hostname that doesn't exactly map what we have stored.
|
||||
|
||||
def return_anyway(context, host_name):
|
||||
return objects.Service(host=host_name.upper())
|
||||
|
||||
mock_get_service.side_effect = return_anyway
|
||||
|
||||
aggr = self.api.create_aggregate(self.context, 'fake_aggregate',
|
||||
'fake_zone')
|
||||
fake_notifier.NOTIFICATIONS = []
|
||||
values = _create_service_entries(self.context)
|
||||
fake_host = values[0][1][0]
|
||||
self.assertRaises(exception.ComputeHostNotFound,
|
||||
self.api.add_host_to_aggregate,
|
||||
self.context, aggr.id, fake_host)
|
||||
mock_add_host.assert_not_called()
|
||||
|
||||
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.'
|
||||
'aggregate_add_host')
|
||||
@mock.patch('nova.objects.HostMapping.get_by_host')
|
||||
|
@ -12285,7 +12308,9 @@ class ComputeAPIAggrCallsSchedulerTestCase(test.NoDBTestCase):
|
|||
agg = objects.Aggregate(name='fake', metadata={}, uuid=uuids.agg)
|
||||
agg.add_host = mock.Mock()
|
||||
with test.nested(
|
||||
mock.patch.object(objects.Service, 'get_by_compute_host'),
|
||||
mock.patch.object(objects.Service, 'get_by_compute_host',
|
||||
return_value=objects.Service(
|
||||
host='fakehost')),
|
||||
mock.patch.object(objects.Aggregate, 'get_by_id',
|
||||
return_value=agg)):
|
||||
self.api.add_host_to_aggregate(self.context, 1, 'fakehost')
|
||||
|
|
|
@ -721,8 +721,12 @@ class ComputeAggregateAPITestCase(test.TestCase):
|
|||
fixtures.MockPatch('nova.objects.HostMapping.get_by_host'))
|
||||
self.useFixture(
|
||||
fixtures.MockPatch('nova.context.set_target_cell'))
|
||||
self.useFixture(
|
||||
fixtures.MockPatch('nova.objects.Service.get_by_compute_host'))
|
||||
mock_service_get_by_compute_host = (
|
||||
self.useFixture(
|
||||
fixtures.MockPatch(
|
||||
'nova.objects.Service.get_by_compute_host')).mock)
|
||||
mock_service_get_by_compute_host.return_value = (
|
||||
objects.Service(host='fake-host'))
|
||||
|
||||
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.'
|
||||
'aggregate_add_host')
|
||||
|
|
Loading…
Reference in New Issue