Exemple #1
0
    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
Exemple #2
0
    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
Exemple #3
0
    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
Exemple #4
0
    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()
Exemple #5
0
    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)