Merge "Fixes KeyError: 'sr_uuid' when booting from volume on xenapi"
This commit is contained in:
		@@ -10,6 +10,29 @@ from nova.virt.xenapi import vm_utils
 | 
			
		||||
from nova.virt.xenapi import volume_utils
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
XENSM_TYPE = 'xensm'
 | 
			
		||||
ISCSI_TYPE = 'iscsi'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_fake_dev_params(sr_type):
 | 
			
		||||
    fakes = {XENSM_TYPE: {'sr_uuid': 'falseSR',
 | 
			
		||||
                          'name_label': 'fake_storage',
 | 
			
		||||
                          'name_description': 'test purposes',
 | 
			
		||||
                          'server': 'myserver',
 | 
			
		||||
                          'serverpath': '/local/scratch/myname',
 | 
			
		||||
                          'sr_type': 'nfs',
 | 
			
		||||
                          'introduce_sr_keys': ['server',
 | 
			
		||||
                                                'serverpath',
 | 
			
		||||
                                                'sr_type'],
 | 
			
		||||
                          'vdi_uuid': 'falseVDI'},
 | 
			
		||||
             ISCSI_TYPE: {'volume_id': 'fake_volume_id',
 | 
			
		||||
                          'target_lun': 1,
 | 
			
		||||
                          'target_iqn': 'fake_iqn:volume-fake_volume_id',
 | 
			
		||||
                          'target_portal': u'localhost:3260',
 | 
			
		||||
                          'target_discovered': False}, }
 | 
			
		||||
    return fakes[sr_type]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GetInstanceForVdisForSrTestCase(stubs.XenAPITestBase):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(GetInstanceForVdisForSrTestCase, self).setUp()
 | 
			
		||||
@@ -50,15 +73,8 @@ class GetInstanceForVdisForSrTestCase(stubs.XenAPITestBase):
 | 
			
		||||
 | 
			
		||||
        self.assertEquals([], result)
 | 
			
		||||
 | 
			
		||||
    def test_get_vdis_for_boot_from_vol(self):
 | 
			
		||||
        dev_params = {'sr_uuid': 'falseSR',
 | 
			
		||||
                      'name_label': 'fake_storage',
 | 
			
		||||
                      'name_description': 'test purposes',
 | 
			
		||||
                      'server': 'myserver',
 | 
			
		||||
                      'serverpath': '/local/scratch/myname',
 | 
			
		||||
                      'sr_type': 'nfs',
 | 
			
		||||
                      'introduce_sr_keys': ['server', 'serverpath', 'sr_type'],
 | 
			
		||||
                      'vdi_uuid': 'falseVDI'}
 | 
			
		||||
    def test_get_vdis_for_boot_from_vol_with_sr_uuid(self):
 | 
			
		||||
        dev_params = get_fake_dev_params(XENSM_TYPE)
 | 
			
		||||
        stubs.stubout_session(self.stubs, fake.SessionBase)
 | 
			
		||||
        driver = xenapi_conn.XenAPIDriver(False)
 | 
			
		||||
 | 
			
		||||
@@ -74,18 +90,20 @@ class GetInstanceForVdisForSrTestCase(stubs.XenAPITestBase):
 | 
			
		||||
            return None
 | 
			
		||||
 | 
			
		||||
        self.stubs.Set(volume_utils, 'introduce_sr', bad_introduce_sr)
 | 
			
		||||
        dev_params = {'sr_uuid': 'falseSR',
 | 
			
		||||
                      'name_label': 'fake_storage',
 | 
			
		||||
                      'name_description': 'test purposes',
 | 
			
		||||
                      'server': 'myserver',
 | 
			
		||||
                      'serverpath': '/local/scratch/myname',
 | 
			
		||||
                      'sr_type': 'nfs',
 | 
			
		||||
                      'introduce_sr_keys': ['server', 'serverpath', 'sr_type'],
 | 
			
		||||
                      'vdi_uuid': 'falseVDI'}
 | 
			
		||||
        dev_params = get_fake_dev_params(XENSM_TYPE)
 | 
			
		||||
        self.assertRaises(exception.NovaException,
 | 
			
		||||
                          vm_utils.get_vdis_for_boot_from_vol,
 | 
			
		||||
                          driver._session, dev_params)
 | 
			
		||||
 | 
			
		||||
    def test_get_vdis_for_boot_from_iscsi_vol_missing_sr_uuid(self):
 | 
			
		||||
        dev_params = get_fake_dev_params(ISCSI_TYPE)
 | 
			
		||||
        stubs.stubout_session(self.stubs, fake.SessionBase)
 | 
			
		||||
        driver = xenapi_conn.XenAPIDriver(False)
 | 
			
		||||
 | 
			
		||||
        result = vm_utils.get_vdis_for_boot_from_vol(driver._session,
 | 
			
		||||
                                                     dev_params)
 | 
			
		||||
        self.assertNotEquals(result['root']['uuid'], None)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VMRefOrRaiseVMFoundTestCase(test.TestCase):
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -462,35 +462,29 @@ def create_vdi(session, sr_ref, instance, name_label, disk_type, virtual_size,
 | 
			
		||||
 | 
			
		||||
def get_vdis_for_boot_from_vol(session, dev_params):
 | 
			
		||||
    vdis = {}
 | 
			
		||||
    sr_uuid = dev_params['sr_uuid']
 | 
			
		||||
    sr_ref = volume_utils.find_sr_by_uuid(session,
 | 
			
		||||
                                          sr_uuid)
 | 
			
		||||
    sr_uuid, label, sr_params = volume_utils.parse_sr_info(dev_params)
 | 
			
		||||
    sr_ref = volume_utils.find_sr_by_uuid(session, sr_uuid)
 | 
			
		||||
    # Try introducing SR if it is not present
 | 
			
		||||
    if not sr_ref:
 | 
			
		||||
        if 'name_label' not in dev_params:
 | 
			
		||||
            label = 'tempSR-%s' % dev_params['volume_id']
 | 
			
		||||
        else:
 | 
			
		||||
            label = dev_params['name_label']
 | 
			
		||||
 | 
			
		||||
        if 'name_description' not in dev_params:
 | 
			
		||||
            desc = ''
 | 
			
		||||
        else:
 | 
			
		||||
            desc = dev_params.get('name_description')
 | 
			
		||||
        sr_params = {}
 | 
			
		||||
        for k in dev_params['introduce_sr_keys']:
 | 
			
		||||
            sr_params[k] = dev_params[k]
 | 
			
		||||
 | 
			
		||||
        sr_params['name_description'] = desc
 | 
			
		||||
        sr_ref = volume_utils.introduce_sr(session, sr_uuid, label,
 | 
			
		||||
                                           sr_params)
 | 
			
		||||
        sr_ref = volume_utils.introduce_sr(session, sr_uuid, label, sr_params)
 | 
			
		||||
 | 
			
		||||
    if sr_ref is None:
 | 
			
		||||
        raise exception.NovaException(_('SR not present and could not be '
 | 
			
		||||
                                        'introduced'))
 | 
			
		||||
    else:
 | 
			
		||||
        if 'vdi_uuid' in dev_params:
 | 
			
		||||
            session.call_xenapi("SR.scan", sr_ref)
 | 
			
		||||
        return {'root': dict(uuid=dev_params['vdi_uuid'],
 | 
			
		||||
            vdis = {'root': dict(uuid=dev_params['vdi_uuid'],
 | 
			
		||||
                    file=None, osvol=True)}
 | 
			
		||||
        else:
 | 
			
		||||
            try:
 | 
			
		||||
                vdi_ref = volume_utils.introduce_vdi(session, sr_ref)
 | 
			
		||||
                vdi_rec = session.call_xenapi("VDI.get_record", vdi_ref)
 | 
			
		||||
                vdis = {'root': dict(uuid=vdi_rec['uuid'],
 | 
			
		||||
                                     file=None, osvol=True)}
 | 
			
		||||
            except volume_utils.StorageError, exc:
 | 
			
		||||
                LOG.exception(exc)
 | 
			
		||||
                volume_utils.forget_sr(session, sr_uuid)
 | 
			
		||||
    return vdis
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -523,8 +517,7 @@ def get_vdis_for_instance(context, session, instance, name_label, image,
 | 
			
		||||
            bdm_root_dev = block_device_info['block_device_mapping'][0]
 | 
			
		||||
            dev_params = bdm_root_dev['connection_info']['data']
 | 
			
		||||
            LOG.debug(dev_params)
 | 
			
		||||
            return get_vdis_for_boot_from_vol(session,
 | 
			
		||||
                                             dev_params)
 | 
			
		||||
            return get_vdis_for_boot_from_vol(session, dev_params)
 | 
			
		||||
    return _create_image(context, session, instance, name_label, image,
 | 
			
		||||
                        image_type)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -67,8 +67,9 @@ def create_sr(session, label, params):
 | 
			
		||||
 | 
			
		||||
def introduce_sr(session, sr_uuid, label, params):
 | 
			
		||||
    LOG.debug(_("introducing sr within volume_utils"))
 | 
			
		||||
    type = params['sr_type']
 | 
			
		||||
    del params['sr_type']
 | 
			
		||||
    # If the sr_type is missing, we assume we are
 | 
			
		||||
    # using the default iscsi back-end
 | 
			
		||||
    type = params.pop('sr_type', 'iscsi')
 | 
			
		||||
    LOG.debug(_('type is = %s') % type)
 | 
			
		||||
    if 'name_description' in params:
 | 
			
		||||
        desc = params['name_description']
 | 
			
		||||
@@ -283,18 +284,29 @@ def get_device_number(mountpoint):
 | 
			
		||||
    return device_number
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def parse_sr_info(connection_data, description=''):
 | 
			
		||||
    label = connection_data.pop('name_label',
 | 
			
		||||
                                'tempSR-%s' % connection_data.get('volume_id'))
 | 
			
		||||
    params = {}
 | 
			
		||||
    if 'sr_uuid' not in connection_data:
 | 
			
		||||
        params = parse_volume_info(connection_data)
 | 
			
		||||
        # This magic label sounds a lot like 'False Disc' in leet-speak
 | 
			
		||||
        uuid = "FA15E-D15C-" + str(params['id'])
 | 
			
		||||
    else:
 | 
			
		||||
        uuid = connection_data['sr_uuid']
 | 
			
		||||
        for k in connection_data.get('introduce_sr_keys', {}):
 | 
			
		||||
            params[k] = connection_data[k]
 | 
			
		||||
    params['name_description'] = connection_data.get('name_description',
 | 
			
		||||
                                                     description)
 | 
			
		||||
 | 
			
		||||
    return (uuid, label, params)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def parse_volume_info(connection_data):
 | 
			
		||||
    """
 | 
			
		||||
    Parse device_path and mountpoint as they can be used by XenAPI.
 | 
			
		||||
    In particular, the mountpoint (e.g. /dev/sdc) must be translated
 | 
			
		||||
    into a numeric literal.
 | 
			
		||||
    FIXME(armando):
 | 
			
		||||
    As for device_path, currently cannot be used as it is,
 | 
			
		||||
    because it does not contain target information. As for interim
 | 
			
		||||
    solution, target details are passed either via Flags or obtained
 | 
			
		||||
    by iscsiadm. Long-term solution is to add a few more fields to the
 | 
			
		||||
    db in the iscsi_target table with the necessary info and modify
 | 
			
		||||
    the iscsi driver to set them.
 | 
			
		||||
    """
 | 
			
		||||
    volume_id = connection_data['volume_id']
 | 
			
		||||
    target_portal = connection_data['target_portal']
 | 
			
		||||
@@ -369,12 +381,3 @@ def _get_target_port(iscsi_string):
 | 
			
		||||
        return iscsi_string[iscsi_string.find(':') + 1:]
 | 
			
		||||
    elif iscsi_string is None or CONF.target_port:
 | 
			
		||||
        return CONF.target_port
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _get_iqn(iscsi_string, id):
 | 
			
		||||
    """Retrieve target IQN"""
 | 
			
		||||
    if iscsi_string:
 | 
			
		||||
        return iscsi_string
 | 
			
		||||
    elif iscsi_string is None or CONF.iqn_prefix:
 | 
			
		||||
        volume_id = _get_volume_id(id)
 | 
			
		||||
        return '%s:%s' % (CONF.iqn_prefix, volume_id)
 | 
			
		||||
 
 | 
			
		||||
@@ -130,28 +130,9 @@ class VolumeOps(object):
 | 
			
		||||
    def connect_volume(self, connection_data, dev_number, instance_name,
 | 
			
		||||
                       vm_ref):
 | 
			
		||||
 | 
			
		||||
        if 'name_label' not in connection_data:
 | 
			
		||||
            label = 'tempSR-%s' % connection_data['volume_id']
 | 
			
		||||
        else:
 | 
			
		||||
            label = connection_data['name_label']
 | 
			
		||||
            del connection_data['name_label']
 | 
			
		||||
 | 
			
		||||
        if 'name_description' not in connection_data:
 | 
			
		||||
            desc = 'Disk-for:%s' % instance_name
 | 
			
		||||
        else:
 | 
			
		||||
            desc = connection_data['name_description']
 | 
			
		||||
 | 
			
		||||
        sr_params = {}
 | 
			
		||||
        if u'sr_uuid' not in connection_data:
 | 
			
		||||
            sr_params = volume_utils.parse_volume_info(connection_data)
 | 
			
		||||
            uuid = "FA15E-D15C-" + str(sr_params['id'])
 | 
			
		||||
            sr_params['sr_type'] = 'iscsi'
 | 
			
		||||
        else:
 | 
			
		||||
            uuid = connection_data['sr_uuid']
 | 
			
		||||
            for k in connection_data['introduce_sr_keys']:
 | 
			
		||||
                sr_params[k] = connection_data[k]
 | 
			
		||||
 | 
			
		||||
        sr_params['name_description'] = desc
 | 
			
		||||
        description = 'Disk-for:%s' % instance_name
 | 
			
		||||
        uuid, label, sr_params = volume_utils.parse_sr_info(connection_data,
 | 
			
		||||
                                                            description)
 | 
			
		||||
 | 
			
		||||
        # Introduce SR
 | 
			
		||||
        try:
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user