Merge "XenAPI: XCP2.1+ Swallow VDI_NOT_IN_MAP Exception"

This commit is contained in:
Zuul 2018-03-12 14:08:20 +00:00 committed by Gerrit Code Review
commit 4f29ee3797
3 changed files with 109 additions and 4 deletions

View File

@ -1794,6 +1794,78 @@ class LiveMigrateHelperTestCase(VMOpsTestBase):
self._call_live_migrate_command_with_migrate_send_data,
migrate_data)
@mock.patch.object(vmops.VMOps, '_call_live_migrate_command')
def test_check_can_live_migrate_source_with_xcp2(self, mock_call_migrate):
ctxt = 'ctxt'
fake_instance = {"name": "fake_instance"}
fake_dest_check_data = objects.XenapiLiveMigrateData()
fake_dest_check_data.block_migration = True
mock_call_migrate.side_effect = \
xenapi_fake.xenapi_session.XenAPI.Failure(['VDI_NOT_IN_MAP'])
with mock.patch.object(self.vmops,
'_get_iscsi_srs') as mock_iscsi_srs, \
mock.patch.object(self.vmops,
'_get_vm_opaque_ref') as mock_vm, \
mock.patch.object(self.vmops,
'_get_host_software_versions') as mock_host_sw:
mock_iscsi_srs.return_value = []
mock_vm.return_value = 'vm_ref'
mock_host_sw.return_value = {'platform_name': 'XCP',
'platform_version': '2.1.0'}
fake_returned_data = self.vmops.check_can_live_migrate_source(
ctxt, fake_instance, fake_dest_check_data)
self.assertEqual(fake_returned_data, fake_dest_check_data)
@mock.patch.object(vmops.VMOps, '_call_live_migrate_command')
def test_check_can_live_migrate_source_with_xcp2_vif_raise(self,
mock_call_migrate):
ctxt = 'ctxt'
fake_instance = {"name": "fake_instance"}
fake_dest_check_data = objects.XenapiLiveMigrateData()
fake_dest_check_data.block_migration = True
mock_call_migrate.side_effect = \
xenapi_fake.xenapi_session.XenAPI.Failure(['VIF_NOT_IN_MAP'])
with mock.patch.object(self.vmops,
'_get_iscsi_srs') as mock_iscsi_srs, \
mock.patch.object(self.vmops,
'_get_vm_opaque_ref') as mock_vm, \
mock.patch.object(self.vmops,
'_get_host_software_versions') as mock_host_sw:
mock_iscsi_srs.return_value = []
mock_vm.return_value = 'vm_ref'
mock_host_sw.return_value = {'platform_name': 'XCP',
'platform_version': '2.1.0'}
self.assertRaises(exception.MigrationPreCheckError,
self.vmops.check_can_live_migrate_source, ctxt,
fake_instance, fake_dest_check_data)
@mock.patch.object(vmops.VMOps, '_call_live_migrate_command')
def test_check_can_live_migrate_source_with_xcp2_sw_raise(self,
mock_call_migrate):
ctxt = 'ctxt'
fake_instance = {"name": "fake_instance"}
fake_dest_check_data = objects.XenapiLiveMigrateData()
fake_dest_check_data.block_migration = True
mock_call_migrate.side_effect = \
xenapi_fake.xenapi_session.XenAPI.Failure(['VDI_NOT_IN_MAP'])
with mock.patch.object(self.vmops,
'_get_iscsi_srs') as mock_iscsi_srs, \
mock.patch.object(self.vmops,
'_get_vm_opaque_ref') as mock_vm, \
mock.patch.object(self.vmops,
'_get_host_software_versions') as mock_host_sw:
mock_iscsi_srs.return_value = []
mock_vm.return_value = 'vm_ref'
mock_host_sw.return_value = {'platform_name': 'XCP',
'platform_version': '1.1.0'}
self.assertRaises(exception.MigrationPreCheckError,
self.vmops.check_can_live_migrate_source, ctxt,
fake_instance, fake_dest_check_data)
def test_generate_vif_network_map(self):
with mock.patch.object(self._session.VIF,
'get_other_config') as mock_other_config, \

View File

@ -109,11 +109,14 @@ def _create_pool(name_label):
{'name_label': name_label})
def create_host(name_label, hostname='fake_name', address='fake_addr'):
def create_host(name_label, hostname='fake_name', address='fake_addr',
software_version={'platform_name': 'fake_platform',
'platform_version': '1.0.0'}):
host_ref = _create_object('host',
{'name_label': name_label,
'hostname': hostname,
'address': address})
{'name_label': name_label,
'hostname': hostname,
'address': address,
'software_version': software_version})
host_default_sr_ref = _create_local_srs(host_ref)
_create_local_pif(host_ref)

View File

@ -36,6 +36,7 @@ from oslo_utils import netutils
from oslo_utils import strutils
from oslo_utils import timeutils
from oslo_utils import units
from oslo_utils import versionutils
import six
from nova import block_device
@ -2227,6 +2228,22 @@ class VMOps(object):
host_uuid = self._get_host_uuid_from_aggregate(context, hostname)
return self._session.call_xenapi("host.get_by_uuid", host_uuid)
def _get_host_ref_no_aggr(self):
# Pull the current host ref from Dom0's resident_on field. This
# allows us a simple way to pull the accurate host without aggregates
dom0_rec = self._session.call_xenapi("VM.get_all_records_where",
'field "domid"="0"')
dom0_ref = list(dom0_rec.keys())[0]
return dom0_rec[dom0_ref]['resident_on']
def _get_host_software_versions(self):
# Get software versions from host.get_record.
# Works around aggregate checking as not all places use aggregates.
host_ref = self._get_host_ref_no_aggr()
host_rec = self._session.call_xenapi("host.get_record", host_ref)
return host_rec['software_version']
def _get_network_ref(self):
# Get the network to for migrate.
# This is the one associated with the pif marked management. From cli:
@ -2345,14 +2362,27 @@ class VMOps(object):
raise exception.MigrationError(reason=_('XAPI supporting '
'relax-xsm-sr-check=true required'))
# TODO(bkaminski): This entire block needs to be removed from this
# if statement. Live Migration should assert_can_migrate either way.
if ('block_migration' in dest_check_data and
dest_check_data.block_migration):
vm_ref = self._get_vm_opaque_ref(instance_ref)
host_sw = self._get_host_software_versions()
host_pfv = host_sw['platform_version']
try:
self._call_live_migrate_command(
"VM.assert_can_migrate", vm_ref, dest_check_data)
except self._session.XenAPI.Failure as exc:
reason = exc.details[0]
# XCP>=2.1 Will error on this assert call if iSCSI are attached
# as the SR has not been configured on the hypervisor at this
# point in the migration. We swallow this exception until a
# more intensive refactor can be done to correct this.
if ("VDI_NOT_IN_MAP" in reason and
host_sw['platform_name'] == "XCP" and
versionutils.is_compatible("2.1.0", host_pfv)):
LOG.debug("Skipping exception for XCP>=2.1.0, %s", reason)
return dest_check_data
msg = _('assert_can_migrate failed because: %s') % reason
LOG.debug(msg, exc_info=True)
raise exception.MigrationPreCheckError(reason=msg)