Merge "XenAPI: XCP2.1+ Swallow VDI_NOT_IN_MAP Exception"
This commit is contained in:
commit
4f29ee3797
@ -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, \
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user