Beispiel #1
0
    def _find_share(self, volume_size_in_gib):
        """Choose NFS share among available ones for given volume size.

        For instances with more than one share that meets the criteria, the
        share with the least "allocated" space will be selected.

        :param volume_size_in_gib: int size in GB
        """

        if not self._mounted_shares:
            raise exception.NfsNoSharesMounted()

        target_share = None
        target_share_reserved = 0

        for nfs_share in self._mounted_shares:
            if not self._is_share_eligible(nfs_share, volume_size_in_gib):
                continue
            _total_size, _total_available, total_allocated = \
                self._get_capacity_info(nfs_share)
            if target_share is not None:
                if target_share_reserved > total_allocated:
                    target_share = nfs_share
                    target_share_reserved = total_allocated
            else:
                target_share = nfs_share
                target_share_reserved = total_allocated

        if target_share is None:
            raise exception.NfsNoSuitableShareFound(
                volume_size=volume_size_in_gib)

        LOG.debug('Selected %s as target nfs share.', target_share)

        return target_share
Beispiel #2
0
    def create_volume(self, volume):
        """Creates a volume.

        :param volume: volume reference
        """

        self._ensure_shares_mounted()
        extra_specs = get_volume_extra_specs(volume)
        eligible = self._find_containers(volume['size'], extra_specs)
        if not eligible:
            raise exception.NfsNoSuitableShareFound(volume_size=volume['size'])
        for sh in eligible:
            try:
                if self.ssc_enabled:
                    volume['provider_location'] = sh.export['path']
                else:
                    volume['provider_location'] = sh
                LOG.info(_('casted to %s') % volume['provider_location'])
                self._do_create_volume(volume)
                return {'provider_location': volume['provider_location']}
            except Exception:
                LOG.warn(
                    _("Exception creating vol %(name)s"
                      " on share %(share)s") % {
                          'name': volume['name'],
                          'share': volume['provider_location']
                      })
                volume['provider_location'] = None
            finally:
                if self.ssc_enabled:
                    self._update_stale_vols(volume=sh)
        msg = _("Volume %s could not be created on shares.")
        raise exception.VolumeBackendAPIException(data=msg % (volume['name']))
Beispiel #3
0
    def _find_share(self, volume_size_in_gib):
        """Choose NFS share among available ones for given volume size.

        For instances with more than one share that meets the criteria, the
        share with the least "allocated" space will be selected.

        :param volume_size_in_gib: int size in GB
        """

        if not self._mounted_shares:
            raise exception.NfsNoSharesMounted()

        target_share = None
        if self.configuration.nfs_round_robin:
            # Round Robin volume placement on shares

            LOG.debug(_("_find_share using round robin"))

            for nfs_share, pos in self._round_robin(self._mounted_shares):
                if not self._is_share_eligible(nfs_share, volume_size_in_gib):
                    continue
                target_share = nfs_share
                self.last_rr_pos = pos
                break
        else:
            # Place volume on share with the most free space.

            LOG.debug(_("_find_share using select most free"))

            target_share_reserved = 0

            for nfs_share in self._mounted_shares:
                if not self._is_share_eligible(nfs_share, volume_size_in_gib):
                    continue
                total_size, total_available, total_allocated = \
                    self._get_capacity_info(nfs_share)
                if target_share is not None:
                    if target_share_reserved > total_allocated:
                        target_share = nfs_share
                        target_share_reserved = total_allocated
                else:
                    target_share = nfs_share
                    target_share_reserved = total_allocated

        if target_share is None:
            raise exception.NfsNoSuitableShareFound(
                volume_size=volume_size_in_gib)

        LOG.debug('Selected %s as target nfs share.', target_share)

        return target_share
Beispiel #4
0
    def _find_share(self, volume_size_for):
        """Choose NFS share among available ones for given volume size. Current
        implementation looks for greatest capacity
        :param volume_size_for: int size in Gb
        """

        if not self._mounted_shares:
            raise exception.NfsNoSharesMounted()

        greatest_size = 0
        greatest_share = None

        for nfs_share in self._mounted_shares:
            capacity = self._get_available_capacity(nfs_share)[0]
            if capacity > greatest_size:
                greatest_share = nfs_share
                greatest_size = capacity

        if volume_size_for * 1024 * 1024 * 1024 > greatest_size:
            raise exception.NfsNoSuitableShareFound(
                volume_size=volume_size_for)
        return greatest_share
Beispiel #5
0
    def _find_share(self, volume_size_in_gib):
        """Choose NFS share among available ones for given volume size.

        First validation step: ratio of actual space (used_space / total_space)
        is less than 'nfs_used_ratio'.

        Second validation step: apparent space allocated (differs from actual
        space used when using sparse files) and compares the apparent available
        space (total_available * nfs_oversub_ratio) to ensure enough space is
        available for the new volume.

        For instances with more than one share that meets the criteria, the
        share with the least "allocated" space will be selected.

        :param volume_size_in_gib: int size in GB
        """

        if not self._mounted_shares:
            raise exception.NfsNoSharesMounted()

        target_share = None
        target_share_reserved = 0

        used_ratio = self.configuration.nfs_used_ratio
        oversub_ratio = self.configuration.nfs_oversub_ratio

        requested_volume_size = volume_size_in_gib * units.GiB

        for nfs_share in self._mounted_shares:
            total_size, total_available, total_allocated = \
                self._get_capacity_info(nfs_share)
            apparent_size = max(0, total_size * oversub_ratio)
            apparent_available = max(0, apparent_size - total_allocated)
            used = (total_size - total_available) / total_size
            if used > used_ratio:
                # NOTE(morganfainberg): We check the used_ratio first since
                # with oversubscription it is possible to not have the actual
                # available space but be within our oversubscription limit
                # therefore allowing this share to still be selected as a valid
                # target.
                LOG.debug(_('%s is above nfs_used_ratio'), nfs_share)
                continue
            if apparent_available <= requested_volume_size:
                LOG.debug(_('%s is above nfs_oversub_ratio'), nfs_share)
                continue
            if total_allocated / total_size >= oversub_ratio:
                LOG.debug(_('%s reserved space is above nfs_oversub_ratio'),
                          nfs_share)
                continue

            if target_share is not None:
                if target_share_reserved > total_allocated:
                    target_share = nfs_share
                    target_share_reserved = total_allocated
            else:
                target_share = nfs_share
                target_share_reserved = total_allocated

        if target_share is None:
            raise exception.NfsNoSuitableShareFound(
                volume_size=volume_size_in_gib)

        LOG.debug(_('Selected %s as target nfs share.'), target_share)

        return target_share