Beispiel #1
0
    def connect_volume(self, connection_properties):
        """Attach the volume to instance_name.

        :param connection_properties: The dictionary that describes all
                                      of the target volume attributes.
        :type connection_properties: dict
        :returns: dict

        connection_properties for Fibre Channel must include:
        target_wwn - World Wide Name
        target_lun - LUN id of the volume
        """
        LOG.debug("execute = %s", self._execute)
        device_info = {'type': 'block'}

        hbas = self._linuxfc.get_fc_hbas_info()
        host_devices = self._get_possible_volume_paths(connection_properties,
                                                       hbas)

        if len(host_devices) == 0:
            # this is empty because we don't have any FC HBAs
            LOG.warning("We are unable to locate any Fibre Channel devices")
            raise exception.NoFibreChannelHostsFound()

        # The /dev/disk/by-path/... node is not always present immediately
        # We only need to find the first device.  Once we see the first device
        # multipath will have any others.
        def _wait_for_device_discovery(host_devices):
            tries = self.tries
            for device in host_devices:
                LOG.debug("Looking for Fibre Channel dev %(device)s",
                          {'device': device})
                if os.path.exists(device):
                    self.host_device = device
                    # get the /dev/sdX device.  This is used
                    # to find the multipath device.
                    self.device_name = os.path.realpath(device)
                    raise loopingcall.LoopingCallDone()

            if self.tries >= self.device_scan_attempts:
                LOG.error("Fibre Channel volume device not found.")
                raise exception.NoFibreChannelVolumeDeviceFound()

            LOG.info(
                "Fibre Channel volume device not yet found. "
                "Will rescan & retry.  Try number: %(tries)s.",
                {'tries': tries})

            self._linuxfc.rescan_hosts(hbas,
                                       connection_properties['target_lun'])
            self.tries = self.tries + 1

        self.host_device = None
        self.device_name = None
        self.tries = 0
        timer = loopingcall.FixedIntervalLoopingCall(
            _wait_for_device_discovery, host_devices)
        timer.start(interval=2).wait()

        tries = self.tries
        if self.host_device is not None and self.device_name is not None:
            LOG.debug(
                "Found Fibre Channel volume %(name)s "
                "(after %(tries)s rescans)", {
                    'name': self.device_name,
                    'tries': tries
                })

        # find out the WWN of the device
        device_wwn = self._linuxscsi.get_scsi_wwn(self.host_device)
        LOG.debug("Device WWN = '%(wwn)s'", {'wwn': device_wwn})
        device_info['scsi_wwn'] = device_wwn

        # see if the new drive is part of a multipath
        # device.  If so, we'll use the multipath device.
        if self.use_multipath:
            (device_path, multipath_id) = (super(FibreChannelConnector,
                                                 self)._discover_mpath_device(
                                                     device_wwn,
                                                     connection_properties,
                                                     self.device_name))
            if multipath_id:
                # only set the multipath_id if we found one
                device_info['multipath_id'] = multipath_id

        else:
            device_path = self.host_device

        device_info['path'] = device_path
        LOG.debug("connect_volume returning %s", device_info)
        return device_info
Beispiel #2
0
    def connect_volume(self, connection_properties):
        """Attach the volume to instance_name.

        :param connection_properties: The dictionary that describes all
                                      of the target volume attributes.
        :type connection_properties: dict
        :returns: dict

        connection_properties for Fibre Channel must include:
        target_wwn - World Wide Name
        target_lun - LUN id of the volume
        """
        device_info = {'type': 'block'}

        connection_properties = self._add_targets_to_connection_properties(
            connection_properties)

        hbas = self._linuxfc.get_fc_hbas_info()
        if not hbas:
            LOG.warning("We are unable to locate any Fibre Channel devices.")
            raise exception.NoFibreChannelHostsFound()

        host_devices = self._get_possible_volume_paths(
            connection_properties, hbas)

        # The /dev/disk/by-path/... node is not always present immediately
        # We only need to find the first device.  Once we see the first device
        # multipath will have any others.
        def _wait_for_device_discovery(host_devices):
            for device in host_devices:
                LOG.debug("Looking for Fibre Channel dev %(device)s",
                          {'device': device})
                if os.path.exists(device) and self.check_valid_device(device):
                    self.host_device = device
                    # get the /dev/sdX device.  This variable is maintained to
                    # keep the same log output.
                    self.device_name = os.path.realpath(device)
                    raise loopingcall.LoopingCallDone()

            if self.tries >= self.device_scan_attempts:
                LOG.error("Fibre Channel volume device not found.")
                raise exception.NoFibreChannelVolumeDeviceFound()

            LOG.info("Fibre Channel volume device not yet found. "
                     "Will rescan & retry.  Try number: %(tries)s.",
                     {'tries': self.tries})

            self._linuxfc.rescan_hosts(hbas, connection_properties)
            self.tries = self.tries + 1

        self.host_device = None
        self.device_name = None
        self.tries = 0
        timer = loopingcall.FixedIntervalLoopingCall(
            _wait_for_device_discovery, host_devices)
        timer.start(interval=2).wait()

        LOG.debug("Found Fibre Channel volume %(name)s "
                  "(after %(tries)s rescans.)",
                  {'name': self.device_name, 'tries': self.tries})

        # find out the WWN of the device
        device_wwn = self._linuxscsi.get_scsi_wwn(self.host_device)
        LOG.debug("Device WWN = '%(wwn)s'", {'wwn': device_wwn})
        device_info['scsi_wwn'] = device_wwn

        # see if the new drive is part of a multipath
        # device.  If so, we'll use the multipath device.
        if self.use_multipath:
            # Pass a symlink, not a real path, otherwise we'll get a real path
            # back if we don't find a multipath and we'll return that to the
            # caller, breaking Nova's encryption which requires a symlink.
            (device_path, multipath_id) = self._discover_mpath_device(
                device_wwn, connection_properties, self.host_device)
            if multipath_id:
                # only set the multipath_id if we found one
                device_info['multipath_id'] = multipath_id

        else:
            device_path = self.host_device

        device_info['path'] = device_path
        return device_info