xenapi: Fix the live-migrate aggregate check

AggregateList now returns [] if the host is not in an
aggregate.  This was causing an IndexError in XenAPI.

This change also replaces the AggregateHostNotFound exception,
which is not caught properly further up the stack, with the
MigrationPreCheckError as this is a suitable substitute since
the aggregate check is only part of the pre migration check.

Probably introduced by Ibcb896b2eef673bce23491161ff394bcc87aa541

Related-Bug: #1557585
Change-Id: Icacd3cbe065ee8598e5e5f03bd73463b95ed2f75
This commit is contained in:
Bob Ball
2016-03-15 16:21:00 +00:00
parent 6e2d6f80dd
commit 38738d79e0
2 changed files with 32 additions and 9 deletions

View File

@@ -1352,6 +1352,28 @@ class LiveMigrateTestCase(VMOpsTestBase):
self.assertEqual({'value': 'fake_migrate_data'},
migrate_data_ret.migrate_send_data)
@mock.patch.object(vmops.objects.AggregateList, 'get_by_host')
def test_get_host_uuid_from_aggregate_no_aggr(self, mock_get_by_host):
mock_get_by_host.return_value = objects.AggregateList(objects=[])
context = "ctx"
hostname = "other_host"
self.assertRaises(exception.MigrationPreCheckError,
self.vmops._get_host_uuid_from_aggregate,
context, hostname)
@mock.patch.object(vmops.objects.AggregateList, 'get_by_host')
def test_get_host_uuid_from_aggregate_bad_aggr(self, mock_get_by_host):
context = "ctx"
hostname = "other_host"
fake_aggregate_obj = objects.Aggregate(hosts=['fake'],
metadata={'this': 'that'})
fake_aggr_list = objects.AggregateList(objects=[fake_aggregate_obj])
mock_get_by_host.return_value = fake_aggr_list
self.assertRaises(exception.MigrationPreCheckError,
self.vmops._get_host_uuid_from_aggregate,
context, hostname)
class LiveMigrateFakeVersionTestCase(VMOpsTestBase):
@mock.patch.object(vmops.VMOps, '_pv_device_reported')

View File

@@ -2100,16 +2100,17 @@ class VMOps(object):
network_info=network_info)
def _get_host_uuid_from_aggregate(self, context, hostname):
current_aggregate = objects.AggregateList.get_by_host(
context, CONF.host, key=pool_states.POOL_FLAG)[0]
if not current_aggregate:
raise exception.AggregateHostNotFound(host=CONF.host)
try:
return current_aggregate.metadata[hostname]
except KeyError:
reason = _('Destination host:%s must be in the same '
'aggregate as the source server') % hostname
aggregate_list = objects.AggregateList.get_by_host(
context, CONF.host, key=pool_states.POOL_FLAG)
reason = _('Destination host:%s must be in the same '
'aggregate as the source server') % hostname
if len(aggregate_list) == 0:
raise exception.MigrationPreCheckError(reason=reason)
if hostname not in aggregate_list[0].metadata:
raise exception.MigrationPreCheckError(reason=reason)
return aggregate_list[0].metadata[hostname]
def _ensure_host_in_aggregate(self, context, hostname):
self._get_host_uuid_from_aggregate(context, hostname)