def _discover_volume_on_vios(self, vios_w, volume_id): """Discovers an hdisk on a single vios for the volume. :param vios_w: VIOS wrapper to process :param volume_id: Volume to discover :returns: Status of the volume or None :returns: Device name or None :returns: LUN or None """ # Get the initiatior WWPNs, targets and Lun for the given VIOS. vio_wwpns, t_wwpns, lun = self._get_hdisk_itls(vios_w) # Build the ITL map and discover the hdisks on the Virtual I/O # Server (if any). itls = hdisk.build_itls(vio_wwpns, t_wwpns, lun) if len(itls) == 0: LOG.debug('No ITLs for VIOS %(vios)s for volume %(volume_id)s.' % {'vios': vios_w.name, 'volume_id': volume_id}) return None, None, None status, device_name, udid = hdisk.discover_hdisk(self.adapter, vios_w.uuid, itls) if hdisk.good_discovery(status, device_name): LOG.info(_LI('Discovered %(hdisk)s on vios %(vios)s for ' 'volume %(volume_id)s. Status code: %(status)s.'), {'hdisk': device_name, 'vios': vios_w.name, 'volume_id': volume_id, 'status': str(status)}) elif status == hdisk.LUAStatus.DEVICE_IN_USE: LOG.warning(_LW('Discovered device %(dev)s for volume %(volume)s ' 'on %(vios)s is in use. Error code: %(status)s.'), {'dev': device_name, 'volume': volume_id, 'vios': vios_w.name, 'status': str(status)}) return status, device_name, udid
def _discover_volume_on_vios(self, vios_w, volume_id): """Discovers an hdisk on a single vios for the volume. :param vios_w: VIOS wrapper to process :param volume_id: Volume to discover :returns: Status of the volume or None :returns: Device name or None :returns: UDID or None """ # Get the initiatior WWPNs, targets and Lun for the given VIOS. vio_wwpns, t_wwpns, lun = self._get_hdisk_itls(vios_w) # Build the ITL map and discover the hdisks on the Virtual I/O # Server (if any). itls = hdisk.build_itls(vio_wwpns, t_wwpns, lun) if len(itls) == 0: LOG.debug('No ITLs for VIOS %(vios)s for volume %(volume_id)s.', { 'vios': vios_w.name, 'volume_id': volume_id }, instance=self.instance) return None, None, None device_id = self.connection_info.get('data', {}).get('pg83NAA') if device_id: device_id = base64.b64encode(device_id.encode()) status, device_name, udid = hdisk.discover_hdisk(self.adapter, vios_w.uuid, itls, device_id=device_id) if hdisk.good_discovery(status, device_name): LOG.info( 'Discovered %(hdisk)s on vios %(vios)s for volume ' '%(volume_id)s. Status code: %(status)s.', { 'hdisk': device_name, 'vios': vios_w.name, 'volume_id': volume_id, 'status': status }, instance=self.instance) elif status == hdisk.LUAStatus.DEVICE_IN_USE: LOG.warning( 'Discovered device %(dev)s for volume %(volume)s ' 'on %(vios)s is in use. Error code: %(status)s.', { 'dev': device_name, 'volume': volume_id, 'vios': vios_w.name, 'status': status }, instance=self.instance) return status, device_name, udid
def _discover_volume_on_vios(self, vios_w, volume_id): """Discovers an hdisk on a single vios for the volume. :param vios_w: VIOS wrapper to process :param volume_id: Volume to discover :returns: Status of the volume or None :returns: Device name or None :returns: LUN or None """ # Get the initiatior WWPNs, targets and Lun for the given VIOS. vio_wwpns, t_wwpns, lun = self._get_hdisk_itls(vios_w) # Build the ITL map and discover the hdisks on the Virtual I/O # Server (if any). itls = hdisk.build_itls(vio_wwpns, t_wwpns, lun) if len(itls) == 0: LOG.debug('No ITLs for VIOS %(vios)s for volume %(volume_id)s.' % { 'vios': vios_w.name, 'volume_id': volume_id }) return None, None, None status, device_name, udid = hdisk.discover_hdisk( self.adapter, vios_w.uuid, itls) if hdisk.good_discovery(status, device_name): LOG.info( _LI('Discovered %(hdisk)s on vios %(vios)s for ' 'volume %(volume_id)s. Status code: %(status)s.'), { 'hdisk': device_name, 'vios': vios_w.name, 'volume_id': volume_id, 'status': str(status) }) elif status == hdisk.LUAStatus.DEVICE_IN_USE: LOG.warn( _LW('Discovered device %(dev)s for volume %(volume)s ' 'on %(vios)s is in use. Error code: %(status)s.'), { 'dev': device_name, 'volume': volume_id, 'vios': vios_w.name, 'status': str(status) }) return status, device_name, udid
def test_discover_hdisk(self, mock_ewget, mock_fsl, mock_alsst, mock_ftsk, mock_luar): def set_luar_side_effect(_stat, _dev): """Set up the lua_recovery mock's side effect. The second return will always be the same - used to verify that we really called twice when appropriate. The first return will be (_stat, _dev, "udid"), per the params. """ mock_luar.reset_mock() mock_luar.side_effect = [(_stat, _dev, 'udid'), ('ok_s', 'ok_h', 'ok_u')] stale_lpar_ids = [12, 34] # All of these should cause a scrub-and-retry retry_rets = [(None, None), (hdisk.LUAStatus.DEVICE_AVAILABLE, None), (hdisk.LUAStatus.FOUND_DEVICE_UNKNOWN_UDID, 'hdisk456')] # These should *not* cause a scrub-and-retry no_retry_rets = [(hdisk.LUAStatus.DEVICE_AVAILABLE, 'hdisk456'), (hdisk.LUAStatus.FOUND_ITL_ERR, 'hdisk456'), (hdisk.LUAStatus.DEVICE_IN_USE, 'hdisk456')] mock_fsl.return_value = stale_lpar_ids for st, dev in retry_rets: set_luar_side_effect(st, dev) self.assertEqual(('ok_s', 'ok_h', 'ok_u'), hdisk.discover_hdisk('adp', 'vuuid', ['itls'])) self.assertEqual(1, mock_fsl.call_count) mock_ftsk.assert_called_with('scrub_vios_vuuid', mock.ANY) self.assertEqual(1, mock_alsst.call_count) mock_luar.assert_has_calls([ mock.call('adp', 'vuuid', ['itls'], vendor=hdisk.LUAType.OTHER) for i in range(2) ]) mock_fsl.reset_mock() mock_alsst.reset_mock() mock_ftsk.reset_mock() for st, dev in no_retry_rets: set_luar_side_effect(st, dev) self.assertEqual((st, dev, 'udid'), hdisk.discover_hdisk('adp', 'vuuid', ['itls'])) self.assertEqual(0, mock_fsl.call_count) self.assertEqual(0, mock_ftsk.call_count) self.assertEqual(0, mock_alsst.call_count) self.assertEqual(1, mock_luar.call_count) mock_luar.assert_called_with('adp', 'vuuid', ['itls'], vendor=hdisk.LUAType.OTHER) # If no stale LPARs found, scrub-and-retry should not be triggered with # either set. mock_fsl.return_value = [] for st, dev in retry_rets + no_retry_rets: set_luar_side_effect(st, dev) self.assertEqual((st, dev, 'udid'), hdisk.discover_hdisk('adp', 'vuuid', ['itls'])) # find_stale_lpars will be called for retry_rets, but not for # no_retry_rets self.assertLessEqual(mock_fsl.call_count, 1) self.assertEqual(0, mock_ftsk.call_count) self.assertEqual(0, mock_alsst.call_count) self.assertEqual(1, mock_luar.call_count) mock_luar.assert_called_with('adp', 'vuuid', ['itls'], vendor=hdisk.LUAType.OTHER) mock_fsl.reset_mock()
def connect_volume(self, adapter, host_uuid, vm_uuid, instance, connection_info): """Connects the volume. :param adapter: The pypowervm adapter. :param host_uuid: The pypowervm UUID of the host. :param vm_uuid: The powervm UUID of the VM. :param instance: The nova instance that the volume should connect to. :param connection_info: Comes from the BDM. Example connection_info: { 'driver_volume_type':'fibre_channel', 'serial':u'10d9934e-b031-48ff-9f02-2ac533e331c8', 'data':{ 'initiator_target_map':{ '21000024FF649105':['500507680210E522'], '21000024FF649104':['500507680210E522'], '21000024FF649107':['500507680210E522'], '21000024FF649106':['500507680210E522'] }, 'target_discovered':False, 'qos_specs':None, 'volume_id':'10d9934e-b031-48ff-9f02-2ac533e331c8', 'target_lun':0, 'access_mode':'rw', 'target_wwn':'500507680210E522' } """ # Get the initiators it_map = connection_info['data']['initiator_target_map'] volume_id = connection_info['data']['volume_id'] lun = connection_info['data']['target_lun'] hdisk_found = False i_wwpns = it_map.keys() t_wwpns = [] # Build single list of target wwpns for it_list in it_map.values(): t_wwpns.extend(it_list) # Get VIOS feed vios_feed = vios.get_active_vioses(adapter, host_uuid) # Iterate through host vios list to find valid hdisks and map to VM. # TODO(IBM): The VIOS should only include the intersection with # defined SCG targets when they are available. for vio_wrap in vios_feed: # TODO(IBM): Investigate if i_wwpns passed to discover_hdisk # should be intersection with VIOS pfc_wwpns itls = hdisk.build_itls(i_wwpns, t_wwpns, lun) status, device_name, udid = hdisk.discover_hdisk( adapter, vio_wrap.uuid, itls) if device_name is not None and status in [ hdisk.LUAStatus.DEVICE_AVAILABLE, hdisk.LUAStatus.FOUND_ITL_ERR]: LOG.info(_LI('Discovered %(hdisk)s on vios %(vios)s for ' 'volume %(volume_id)s. Status code: %(status)s.') % {'hdisk': device_name, 'vios': vio_wrap.name, 'volume_id': volume_id, 'status': str(status)}) self._add_mapping(adapter, host_uuid, vm_uuid, vio_wrap.uuid, device_name) connection_info['data']['target_UDID'] = udid self._set_udid(instance, vio_wrap.uuid, volume_id, udid) LOG.info(_LI('Device attached: %s'), device_name) hdisk_found = True elif status == hdisk.LUAStatus.DEVICE_IN_USE: LOG.warn(_LW('Discovered device %(dev)s for volume %(volume)s ' 'on %(vios)s is in use Errorcode: %(status)s.'), {'dev': device_name, 'volume': volume_id, 'vios': vio_wrap.name, 'status': str(status)}) # A valid hdisk was not found so log and exit if not hdisk_found: msg = (_LE('Failed to discover valid hdisk on any Virtual I/O ' 'Server for volume %(volume_id)s.') % {'volume_id': volume_id}) LOG.error(msg) if device_name is None: device_name = 'None' ex_args = {'backing_dev': device_name, 'instance_name': instance.name, 'reason': six.text_type(msg)} raise pexc.VolumeAttachFailed(**ex_args)