def _weigh_object(self, host_state, weight_properties): """Higher weighers win. We want spreading to be the default.""" reserved = float(host_state.reserved_percentage) / 100 free_space = host_state.free_capacity_gb total_space = host_state.total_capacity_gb if 'unknown' in (total_space, free_space): # NOTE(u_glide): "unknown" capacity always sorts to the bottom if CONF.capacity_weight_multiplier > 0: free = float('-inf') else: free = float('inf') else: total = float(total_space) share_type = weight_properties.get('share_type', {}) use_thin_logic = utils.use_thin_logic(share_type) thin_provisioning = utils.thin_provisioning( host_state.thin_provisioning) if use_thin_logic and thin_provisioning: # NOTE(xyang): Calculate virtual free capacity for thin # provisioning. free = math.floor(total * host_state.max_over_subscription_ratio - host_state.provisioned_capacity_gb - total * reserved) else: # NOTE(xyang): Calculate how much free space is left after # taking into account the reserved space. free = math.floor(free_space - total * reserved) return free
def _weigh_object(self, host_state, weight_properties): """Higher weighers win. We want spreading to be the default.""" reserved = float(host_state.reserved_percentage) / 100 free_space = host_state.free_capacity_gb total_space = host_state.total_capacity_gb if 'unknown' in (total_space, free_space): # NOTE(u_glide): "unknown" capacity always sorts to the bottom if CONF.capacity_weight_multiplier > 0: free = float('-inf') else: free = float('inf') else: total = float(total_space) share_type = weight_properties.get('share_type', {}) use_thin_logic = utils.use_thin_logic(share_type) thin_provisioning = utils.thin_provisioning( host_state.thin_provisioning) if use_thin_logic and thin_provisioning: # NOTE(xyang): Calculate virtual free capacity for thin # provisioning. free = math.floor( total * host_state.max_over_subscription_ratio - host_state.provisioned_capacity_gb - total * reserved) else: # NOTE(xyang): Calculate how much free space is left after # taking into account the reserved space. free = math.floor(free_space - total * reserved) return free
def update_from_share_capability(self, capability, service=None, context=None): """Update information about a pool from its share_node info.""" self.update_capabilities(capability, service) if capability: if self.updated and self.updated > capability['timestamp']: return self.update_backend(capability) self.total_capacity_gb = capability['total_capacity_gb'] self.free_capacity_gb = capability['free_capacity_gb'] self.allocated_capacity_gb = capability.get( 'allocated_capacity_gb', 0) self.qos = capability.get('qos', False) self.reserved_percentage = capability['reserved_percentage'] self.thin_provisioning = scheduler_utils.thin_provisioning( capability.get('thin_provisioning', False)) # NOTE(xyang): provisioned_capacity_gb is the apparent total # capacity of all the shares created on a backend, which is # greater than or equal to allocated_capacity_gb, which is the # apparent total capacity of all the shares created on a backend # in Manila. # NOTE(nidhimittalhada): If 'provisioned_capacity_gb' is not set, # then calculating 'provisioned_capacity_gb' from share sizes # on host, as per information available in manila database. # NOTE(jose-castro-leon): Only calculate provisioned_capacity_gb # on thin provisioned pools self.provisioned_capacity_gb = capability.get( 'provisioned_capacity_gb') if self.thin_provisioning and self.provisioned_capacity_gb is None: self.provisioned_capacity_gb = ( self._estimate_provisioned_capacity(self.host, context=context)) self.max_over_subscription_ratio = capability.get( 'max_over_subscription_ratio', CONF.max_over_subscription_ratio) self.dedupe = capability.get('dedupe', False) self.compression = capability.get('compression', False) self.replication_type = capability.get('replication_type', self.replication_type) self.replication_domain = capability.get('replication_domain') self.sg_consistent_snapshot_support = capability.get( 'sg_consistent_snapshot_support') self.security_service_update_support = capability.get( 'security_service_update_support', False)
def test_thin_provisioning(self, thin_capabilities, thin): thin_provisioning = utils.thin_provisioning(thin_capabilities) self.assertEqual(thin, thin_provisioning)
def host_passes(self, host_state, filter_properties): """Return True if host has sufficient capacity.""" share_size = filter_properties.get('size', 0) if host_state.free_capacity_gb is None: # Fail Safe LOG.error("Free capacity not set: " "share node info collection broken.") return False free_space = host_state.free_capacity_gb total_space = host_state.total_capacity_gb reserved = float(host_state.reserved_percentage) / 100 if free_space == 'unknown': # NOTE(zhiteng) for those back-ends cannot report actual # available capacity, we assume it is able to serve the # request. Even if it was not, the retry mechanism is # able to handle the failure by rescheduling return True elif total_space == 'unknown': # NOTE(xyang): If total_space is 'unknown' and # reserved is 0, we assume the back-ends can serve the request. # If total_space is 'unknown' and reserved # is not 0, we cannot calculate the reserved space. # float(total_space) will throw an exception. total*reserved # also won't work. So the back-ends cannot serve the request. return reserved == 0 and share_size <= free_space total = float(total_space) if total <= 0: LOG.warning("Insufficient free space for share creation. " "Total capacity is %(total).2f on host %(host)s.", {"total": total, "host": host_state.host}) return False # NOTE(xyang): Calculate how much free space is left after taking # into account the reserved space. free = math.floor(free_space - total * reserved) msg_args = {"host": host_state.host, "requested": share_size, "available": free} LOG.debug("Space information for share creation " "on host %(host)s (requested / avail): " "%(requested)s/%(available)s", msg_args) share_type = filter_properties.get('share_type', {}) use_thin_logic = utils.use_thin_logic(share_type) thin_provisioning = utils.thin_provisioning( host_state.thin_provisioning) # NOTE(xyang): Only evaluate using max_over_subscription_ratio # if use_thin_logic and thin_provisioning are True. Check if the # ratio of provisioned capacity over total capacity would exceed # subscription ratio. # If max_over_subscription_ratio = 1, the provisioned_ratio # should still be limited by the max_over_subscription_ratio; # otherwise, it could result in infinite provisioning. if (use_thin_logic and thin_provisioning and host_state.max_over_subscription_ratio >= 1): provisioned_ratio = ((host_state.provisioned_capacity_gb + share_size) / total) if provisioned_ratio > host_state.max_over_subscription_ratio: LOG.warning( "Insufficient free space for thin provisioning. " "The ratio of provisioned capacity over total capacity " "%(provisioned_ratio).2f would exceed the maximum over " "subscription ratio %(oversub_ratio).2f on host " "%(host)s.", {"provisioned_ratio": provisioned_ratio, "oversub_ratio": host_state.max_over_subscription_ratio, "host": host_state.host}) return False else: # NOTE(xyang): Adjust free_virtual calculation based on # free and max_over_subscription_ratio. adjusted_free_virtual = ( free * host_state.max_over_subscription_ratio) return adjusted_free_virtual >= share_size elif (use_thin_logic and thin_provisioning and host_state.max_over_subscription_ratio < 1): LOG.error("Invalid max_over_subscription_ratio: %(ratio)s. " "Valid value should be >= 1.", {"ratio": host_state.max_over_subscription_ratio}) return False if free < share_size: LOG.warning("Insufficient free space for share creation " "on host %(host)s (requested / avail): " "%(requested)s/%(available)s", msg_args) return False return True