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
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']))
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
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
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