def set_nas_security_options(self, is_new_cinder_install): """Determine the setting to use for Secure NAS options. Value of each NAS Security option is checked and updated. If the option is currently 'auto', then it is set to either true or false based upon if this is a new Cinder installation. The RemoteFS variable '_execute_as_root' will be updated for this driver. :param is_new_cinder_install: bool indication of new Cinder install """ doc_html = "https://docs.openstack.org/cinder/latest" \ "/admin/blockstorage-nfs-backend.html" self._ensure_shares_mounted() if not self._mounted_shares: raise exception.NfsNoSharesMounted() nfs_mount = self._get_mount_point_for_share(self._mounted_shares[0]) self.configuration.nas_secure_file_permissions = \ self._determine_nas_security_option_setting( self.configuration.nas_secure_file_permissions, nfs_mount, is_new_cinder_install) LOG.debug('NAS variable secure_file_permissions setting is: %s', self.configuration.nas_secure_file_permissions) if self.configuration.nas_secure_file_permissions == 'false': LOG.warning( "The NAS file permissions mode will be 666 " "(allowing other/world read & write access). " "This is considered an insecure NAS environment. " "Please see %s for information on a secure " "NFS configuration.", doc_html) self.configuration.nas_secure_file_operations = \ self._determine_nas_security_option_setting( self.configuration.nas_secure_file_operations, nfs_mount, is_new_cinder_install) # If secure NAS, update the '_execute_as_root' flag to not # run as the root user; run as process' user ID. # TODO(eharney): need to separate secure NAS vs. execute as root. # There are requirements to run some commands as root even # when running in secure NAS mode. (i.e. read volume file # attached to an instance and owned by qemu:qemu) if self.configuration.nas_secure_file_operations == 'true': self._execute_as_root = False LOG.debug('NAS secure file operations setting is: %s', self.configuration.nas_secure_file_operations) if self.configuration.nas_secure_file_operations == 'false': LOG.warning( "The NAS file operations will be run as " "root: allowing root level access at the storage " "backend. This is considered an insecure NAS " "environment. Please see %s " "for information on a secure NAS configuration.", doc_html)
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 set_nas_security_options(self, is_new_cinder_install): """Determine the setting to use for Secure NAS options. Value of each NAS Security option is checked and updated. If the option is currently 'auto', then it is set to either true or false based upon if this is a new Cinder installation. The RemoteFS variable '_execute_as_root' will be updated for this driver. :param is_new_cinder_install: bool indication of new Cinder install """ doc_html = "http://docs.openstack.org/admin-guide-cloud/content" \ "/nfs_backend.html" self._ensure_shares_mounted() if not self._mounted_shares: raise exception.NfsNoSharesMounted() nfs_mount = self._get_mount_point_for_share(self._mounted_shares[0]) self.configuration.nas_secure_file_permissions = \ self._determine_nas_security_option_setting( self.configuration.nas_secure_file_permissions, nfs_mount, is_new_cinder_install) LOG.debug('NAS variable secure_file_permissions setting is: %s', self.configuration.nas_secure_file_permissions) if self.configuration.nas_secure_file_permissions == 'false': LOG.warning( _LW("The NAS file permissions mode will be 666 " "(allowing other/world read & write access). " "This is considered an insecure NAS environment. " "Please see %s for information on a secure " "NFS configuration."), doc_html) self.configuration.nas_secure_file_operations = \ self._determine_nas_security_option_setting( self.configuration.nas_secure_file_operations, nfs_mount, is_new_cinder_install) # If secure NAS, update the '_execute_as_root' flag to not # run as the root user; run as process' user ID. if self.configuration.nas_secure_file_operations == 'true': self._execute_as_root = False LOG.debug('NAS variable secure_file_operations setting is: %s', self.configuration.nas_secure_file_operations) if self.configuration.nas_secure_file_operations == 'false': LOG.warning( _LW("The NAS file operations will be run as " "root: allowing root level access at the storage " "backend. This is considered an insecure NAS " "environment. Please see %s " "for information on a secure NAS configuration."), doc_html)
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