def _get_share_capacity_info(self, nfs_share): """Returns the share capacity metrics needed by the scheduler.""" used_ratio = self.configuration.nfs_used_ratio oversub_ratio = self.configuration.nfs_oversub_ratio # The scheduler's capacity filter will reduce the amount of # free space that we report to it by the reserved percentage. reserved_ratio = 1 - used_ratio reserved_percentage = round(100 * reserved_ratio) total_size, total_available = self._get_capacity_info(nfs_share) apparent_size = total_size * oversub_ratio apparent_size_gb = na_utils.round_down(apparent_size / units.Gi, '0.01') apparent_free_size = total_available * oversub_ratio apparent_free_gb = na_utils.round_down( float(apparent_free_size) / units.Gi, '0.01') capacity = dict() capacity['reserved_percentage'] = reserved_percentage capacity['total_capacity_gb'] = apparent_size_gb capacity['free_capacity_gb'] = apparent_free_gb return capacity
def _get_pool_stats(self): """Retrieve pool (i.e. NFS share) stats info from SSC volumes.""" pools = [] for nfs_share in self._mounted_shares: capacity = self._get_extended_capacity_info(nfs_share) pool = dict() pool['pool_name'] = nfs_share pool['QoS_support'] = False pool['reserved_percentage'] = 0 # Report pool as reserved when over the configured used_ratio if capacity['used_ratio'] > self.configuration.nfs_used_ratio: pool['reserved_percentage'] = 100 # Report pool as reserved when over the subscribed ratio if capacity['subscribed_ratio'] >=\ self.configuration.nfs_oversub_ratio: pool['reserved_percentage'] = 100 # convert sizes to GB total = float(capacity['apparent_size']) / units.Gi pool['total_capacity_gb'] = na_utils.round_down(total, '0.01') free = float(capacity['apparent_available']) / units.Gi pool['free_capacity_gb'] = na_utils.round_down(free, '0.01') pools.append(pool) return pools
def test_get_pool_stats(self, nfs_sparsed_volumes): self.driver.configuration.nfs_sparsed_volumes = nfs_sparsed_volumes thick = not nfs_sparsed_volumes total_capacity_gb = na_utils.round_down( fake.TOTAL_BYTES / units.Gi, '0.01') free_capacity_gb = na_utils.round_down( fake.AVAILABLE_BYTES / units.Gi, '0.01') provisioned_capacity_gb = total_capacity_gb - free_capacity_gb capacity = { 'reserved_percentage': fake.RESERVED_PERCENTAGE, 'max_over_subscription_ratio': fake.MAX_OVER_SUBSCRIPTION_RATIO, 'total_capacity_gb': total_capacity_gb, 'free_capacity_gb': free_capacity_gb, 'provisioned_capacity_gb': provisioned_capacity_gb, } self.mock_object(self.driver, '_get_share_capacity_info', mock.Mock(return_value=capacity)) result = self.driver._get_pool_stats() expected = [{'pool_name': '192.168.99.24:/fake/export/path', 'QoS_support': False, 'thick_provisioning_support': thick, 'thin_provisioning_support': not thick, 'free_capacity_gb': 12.0, 'total_capacity_gb': 4468.0, 'reserved_percentage': 7, 'max_over_subscription_ratio': 19.0, 'provisioned_capacity_gb': 4456.0}] self.assertEqual(expected, result)
def test_get_pool_stats(self, nfs_sparsed_volumes): self.driver.configuration.nfs_sparsed_volumes = nfs_sparsed_volumes thick = not nfs_sparsed_volumes total_capacity_gb = na_utils.round_down(fake.TOTAL_BYTES / units.Gi, '0.01') free_capacity_gb = na_utils.round_down(fake.AVAILABLE_BYTES / units.Gi, '0.01') provisioned_capacity_gb = total_capacity_gb - free_capacity_gb capacity = { 'reserved_percentage': fake.RESERVED_PERCENTAGE, 'max_over_subscription_ratio': fake.MAX_OVER_SUBSCRIPTION_RATIO, 'total_capacity_gb': total_capacity_gb, 'free_capacity_gb': free_capacity_gb, 'provisioned_capacity_gb': provisioned_capacity_gb, } self.mock_object(self.driver, '_get_share_capacity_info', mock.Mock(return_value=capacity)) result = self.driver._get_pool_stats() expected = [{ 'pool_name': '192.168.99.24:/fake/export/path', 'QoS_support': False, 'thick_provisioning_support': thick, 'thin_provisioning_support': not thick, 'free_capacity_gb': 12.0, 'total_capacity_gb': 4468.0, 'reserved_percentage': 7, 'max_over_subscription_ratio': 19.0, 'provisioned_capacity_gb': 4456.0 }] self.assertEqual(expected, result)
def test_get_pool_stats(self): total_capacity_gb = na_utils.round_down( fake.TOTAL_BYTES / units.Gi, '0.01') free_capacity_gb = na_utils.round_down( fake.AVAILABLE_BYTES / units.Gi, '0.01') capacity = dict( reserved_percentage = fake.RESERVED_PERCENTAGE, total_capacity_gb = total_capacity_gb, free_capacity_gb = free_capacity_gb, ) mock_get_capacity = self.mock_object( self.driver, '_get_share_capacity_info') mock_get_capacity.return_value = capacity mock_get_vol_for_share = self.mock_object( self.driver, '_get_vol_for_share') mock_get_vol_for_share.return_value = None result = self.driver._get_pool_stats() self.assertEqual(fake.RESERVED_PERCENTAGE, result[0]['reserved_percentage']) self.assertEqual(total_capacity_gb, result[0]['total_capacity_gb']) self.assertEqual(free_capacity_gb, result[0]['free_capacity_gb'])
def _get_pool_stats(self, filter_function=None, goodness_function=None): """Retrieve pool (i.e. Data ONTAP volume) stats info from volumes.""" pools = [] self.perf_library.update_performance_cache() for vol in self.vols: volume_name = vol.get_child_content('name') # omit volumes not specified in the config if self.volume_list and volume_name not in self.volume_list: continue # omit root volume if volume_name == self.root_volume_name: continue # ensure good volume state state = vol.get_child_content('state') inconsistent = vol.get_child_content('is-inconsistent') invalid = vol.get_child_content('is-invalid') if (state != 'online' or inconsistent != 'false' or invalid != 'false'): continue pool = dict() pool['pool_name'] = volume_name pool['QoS_support'] = False pool['reserved_percentage'] = (self.reserved_percentage) pool['max_over_subscription_ratio'] = ( self.max_over_subscription_ratio) # convert sizes to GB total = float(vol.get_child_content('size-total') or 0) total /= units.Gi pool['total_capacity_gb'] = na_utils.round_down(total, '0.01') free = float(vol.get_child_content('size-available') or 0) free /= units.Gi pool['free_capacity_gb'] = na_utils.round_down(free, '0.01') pool['provisioned_capacity_gb'] = (round( pool['total_capacity_gb'] - pool['free_capacity_gb'], 2)) thick = ( self.configuration.netapp_lun_space_reservation == 'enabled') pool['thick_provisioning_support'] = thick pool['thin_provisioning_support'] = not thick utilization = self.perf_library.get_node_utilization() pool['utilization'] = na_utils.round_down(utilization, '0.01') pool['filter_function'] = filter_function pool['goodness_function'] = goodness_function pool['consistencygroup_support'] = True pools.append(pool) return pools
def _get_pool_stats(self): """Retrieve pool (i.e. NFS share) stats info from SSC volumes.""" pools = [] for nfs_share in self._mounted_shares: capacity = self._get_extended_capacity_info(nfs_share) pool = dict() pool['pool_name'] = nfs_share pool['QoS_support'] = False pool['reserved_percentage'] = 0 # Report pool as reserved when over the configured used_ratio if capacity['used_ratio'] > self.configuration.nfs_used_ratio: pool['reserved_percentage'] = 100 # Report pool as reserved when over the subscribed ratio if capacity['subscribed_ratio'] >=\ self.configuration.nfs_oversub_ratio: pool['reserved_percentage'] = 100 # convert sizes to GB total = float(capacity['apparent_size']) / units.Gi pool['total_capacity_gb'] = na_utils.round_down(total, '0.01') free = float(capacity['apparent_available']) / units.Gi pool['free_capacity_gb'] = na_utils.round_down(free, '0.01') pools.append(pool) return pools
def _get_pool_stats(self, filter_function=None, goodness_function=None): """Retrieve pool (i.e. Data ONTAP volume) stats info from volumes.""" pools = [] self.perf_library.update_performance_cache() for vol in self.vols: volume_name = vol.get_child_content('name') # omit volumes not specified in the config if self.volume_list and volume_name not in self.volume_list: continue # omit root volume if volume_name == self.root_volume_name: continue # ensure good volume state state = vol.get_child_content('state') inconsistent = vol.get_child_content('is-inconsistent') invalid = vol.get_child_content('is-invalid') if (state != 'online' or inconsistent != 'false' or invalid != 'false'): continue pool = dict() pool['pool_name'] = volume_name pool['QoS_support'] = False pool['reserved_percentage'] = ( self.reserved_percentage) pool['max_over_subscription_ratio'] = ( self.max_over_subscription_ratio) # convert sizes to GB total = float(vol.get_child_content('size-total') or 0) total /= units.Gi pool['total_capacity_gb'] = na_utils.round_down(total, '0.01') free = float(vol.get_child_content('size-available') or 0) free /= units.Gi pool['free_capacity_gb'] = na_utils.round_down(free, '0.01') pool['provisioned_capacity_gb'] = (round( pool['total_capacity_gb'] - pool['free_capacity_gb'], 2)) thick = ( self.configuration.netapp_lun_space_reservation == 'enabled') pool['thick_provisioning_support'] = thick pool['thin_provisioning_support'] = not thick utilization = self.perf_library.get_node_utilization() pool['utilization'] = na_utils.round_down(utilization, '0.01') pool['filter_function'] = filter_function pool['goodness_function'] = goodness_function pools.append(pool) return pools
def test_get_pool_stats(self): total_capacity_gb = na_utils.round_down(fake.TOTAL_BYTES / units.Gi, '0.01') free_capacity_gb = na_utils.round_down(fake.AVAILABLE_BYTES / units.Gi, '0.01') capacity = dict( reserved_percentage=fake.RESERVED_PERCENTAGE, total_capacity_gb=total_capacity_gb, free_capacity_gb=free_capacity_gb, ) mock_get_capacity = self.mock_object(self.driver, '_get_share_capacity_info') mock_get_capacity.return_value = capacity mock_get_vol_for_share = self.mock_object(self.driver, '_get_vol_for_share') mock_get_vol_for_share.return_value = None result = self.driver._get_pool_stats() self.assertEqual(fake.RESERVED_PERCENTAGE, result[0]['reserved_percentage']) self.assertEqual(total_capacity_gb, result[0]['total_capacity_gb']) self.assertEqual(free_capacity_gb, result[0]['free_capacity_gb'])
def _get_share_capacity_info(self, nfs_share): """Returns the share capacity metrics needed by the scheduler.""" used_ratio = self.configuration.nfs_used_ratio oversub_ratio = self.configuration.nfs_oversub_ratio # The scheduler's capacity filter will reduce the amount of # free space that we report to it by the reserved percentage. reserved_ratio = 1 - used_ratio reserved_percentage = round(100 * reserved_ratio) total_size, total_available = self._get_capacity_info(nfs_share) apparent_size = total_size * oversub_ratio apparent_size_gb = na_utils.round_down( apparent_size / units.Gi, '0.01') apparent_free_size = total_available * oversub_ratio apparent_free_gb = na_utils.round_down( float(apparent_free_size) / units.Gi, '0.01') capacity = dict() capacity['reserved_percentage'] = reserved_percentage capacity['total_capacity_gb'] = apparent_size_gb capacity['free_capacity_gb'] = apparent_free_gb return capacity
def _get_pool_stats(self): """Retrieve pool (Data ONTAP volume) stats info from SSC volumes.""" pools = [] if not self.ssc_vols: return pools for vol in self._get_filtered_pools(): pool = dict() pool['pool_name'] = vol.id['name'] pool['QoS_support'] = True pool['reserved_percentage'] = ( self.reserved_percentage) pool['max_over_subscription_ratio'] = ( self.max_over_subscription_ratio) # convert sizes to GB total = float(vol.space['size_total_bytes']) total /= units.Gi pool['total_capacity_gb'] = na_utils.round_down(total, '0.01') free = float(vol.space['size_avl_bytes']) free /= units.Gi pool['free_capacity_gb'] = na_utils.round_down(free, '0.01') pool['provisioned_capacity_gb'] = (round( pool['total_capacity_gb'] - pool['free_capacity_gb'], 2)) pool['netapp_raid_type'] = vol.aggr['raid_type'] pool['netapp_disk_type'] = vol.aggr['disk_type'] mirrored = vol in self.ssc_vols['mirrored'] pool['netapp_mirrored'] = six.text_type(mirrored).lower() pool['netapp_unmirrored'] = six.text_type(not mirrored).lower() dedup = vol in self.ssc_vols['dedup'] pool['netapp_dedup'] = six.text_type(dedup).lower() pool['netapp_nodedup'] = six.text_type(not dedup).lower() compression = vol in self.ssc_vols['compression'] pool['netapp_compression'] = six.text_type(compression).lower() pool['netapp_nocompression'] = six.text_type( not compression).lower() thin = vol in self.ssc_vols['thin'] pool['netapp_thin_provisioned'] = six.text_type(thin).lower() pool['netapp_thick_provisioned'] = six.text_type(not thin).lower() thick = (not thin and self.configuration.netapp_lun_space_reservation == 'enabled') pool['thick_provisioning_support'] = thick pool['thin_provisioning_support'] = not thick pools.append(pool) return pools
def _get_pool_stats(self): """Retrieve pool (i.e. NFS share) stats info from SSC volumes.""" pools = [] for nfs_share in self._mounted_shares: capacity = self._get_extended_capacity_info(nfs_share) pool = dict() pool['pool_name'] = nfs_share pool['QoS_support'] = False pool['reserved_percentage'] = 0 # Report pool as reserved when over the configured used_ratio if capacity['used_ratio'] > self.configuration.nfs_used_ratio: pool['reserved_percentage'] = 100 # Report pool as reserved when over the subscribed ratio if capacity['subscribed_ratio'] >=\ self.configuration.nfs_oversub_ratio: pool['reserved_percentage'] = 100 # convert sizes to GB total = float(capacity['apparent_size']) / units.Gi pool['total_capacity_gb'] = na_utils.round_down(total, '0.01') free = float(capacity['apparent_available']) / units.Gi pool['free_capacity_gb'] = na_utils.round_down(free, '0.01') # add SSC content if available vol = self._get_vol_for_share(nfs_share) if vol and self.ssc_vols: pool['netapp_raid_type'] = vol.aggr['raid_type'] pool['netapp_disk_type'] = vol.aggr['disk_type'] mirrored = vol in self.ssc_vols['mirrored'] pool['netapp_mirrored'] = six.text_type(mirrored).lower() pool['netapp_unmirrored'] = six.text_type(not mirrored).lower() dedup = vol in self.ssc_vols['dedup'] pool['netapp_dedup'] = six.text_type(dedup).lower() pool['netapp_nodedup'] = six.text_type(not dedup).lower() compression = vol in self.ssc_vols['compression'] pool['netapp_compression'] = six.text_type(compression).lower() pool['netapp_nocompression'] = six.text_type( not compression).lower() thin = vol in self.ssc_vols['thin'] pool['netapp_thin_provisioned'] = six.text_type(thin).lower() pool['netapp_thick_provisioned'] = six.text_type( not thin).lower() pools.append(pool) return pools
def _get_pool_stats(self): """Retrieve pool (i.e. NFS share) stats info from SSC volumes.""" pools = [] for nfs_share in self._mounted_shares: capacity = self._get_extended_capacity_info(nfs_share) pool = dict() pool['pool_name'] = nfs_share pool['QoS_support'] = False pool['reserved_percentage'] = 0 # Report pool as reserved when over the configured used_ratio if capacity['used_ratio'] > self.configuration.nfs_used_ratio: pool['reserved_percentage'] = 100 # Report pool as reserved when over the subscribed ratio if capacity['subscribed_ratio'] >=\ self.configuration.nfs_oversub_ratio: pool['reserved_percentage'] = 100 # convert sizes to GB total = float(capacity['apparent_size']) / units.Gi pool['total_capacity_gb'] = na_utils.round_down(total, '0.01') free = float(capacity['apparent_available']) / units.Gi pool['free_capacity_gb'] = na_utils.round_down(free, '0.01') # add SSC content if available vol = self._get_vol_for_share(nfs_share) if vol and self.ssc_vols: pool['netapp_raid_type'] = vol.aggr['raid_type'] pool['netapp_disk_type'] = vol.aggr['disk_type'] mirrored = vol in self.ssc_vols['mirrored'] pool['netapp_mirrored'] = six.text_type(mirrored).lower() pool['netapp_unmirrored'] = six.text_type(not mirrored).lower() dedup = vol in self.ssc_vols['dedup'] pool['netapp_dedup'] = six.text_type(dedup).lower() pool['netapp_nodedup'] = six.text_type(not dedup).lower() compression = vol in self.ssc_vols['compression'] pool['netapp_compression'] = six.text_type(compression).lower() pool['netapp_nocompression'] = six.text_type( not compression).lower() thin = vol in self.ssc_vols['thin'] pool['netapp_thin_provisioned'] = six.text_type(thin).lower() pool['netapp_thick_provisioned'] = six.text_type( not thin).lower() pools.append(pool) return pools
def _get_pool_stats(self): """Retrieve pool (Data ONTAP volume) stats info from SSC volumes.""" pools = [] if not self.ssc_vols: return pools for vol in self._get_filtered_pools(): pool = dict() pool['pool_name'] = vol.id['name'] pool['QoS_support'] = True pool['reserved_percentage'] = (self.reserved_percentage) pool['max_over_subscription_ratio'] = ( self.max_over_subscription_ratio) # convert sizes to GB total = float(vol.space['size_total_bytes']) total /= units.Gi pool['total_capacity_gb'] = na_utils.round_down(total, '0.01') free = float(vol.space['size_avl_bytes']) free /= units.Gi pool['free_capacity_gb'] = na_utils.round_down(free, '0.01') pool['provisioned_capacity_gb'] = (round( pool['total_capacity_gb'] - pool['free_capacity_gb'], 2)) pool['netapp_raid_type'] = vol.aggr['raid_type'] pool['netapp_disk_type'] = vol.aggr['disk_type'] mirrored = vol in self.ssc_vols['mirrored'] pool['netapp_mirrored'] = six.text_type(mirrored).lower() pool['netapp_unmirrored'] = six.text_type(not mirrored).lower() dedup = vol in self.ssc_vols['dedup'] pool['netapp_dedup'] = six.text_type(dedup).lower() pool['netapp_nodedup'] = six.text_type(not dedup).lower() compression = vol in self.ssc_vols['compression'] pool['netapp_compression'] = six.text_type(compression).lower() pool['netapp_nocompression'] = six.text_type( not compression).lower() thin = vol in self.ssc_vols['thin'] pool['netapp_thin_provisioned'] = six.text_type(thin).lower() pool['netapp_thick_provisioned'] = six.text_type(not thin).lower() thick = (not thin and self.configuration.netapp_lun_space_reservation == 'enabled') pool['thick_provisioned_support'] = thick pool['thin_provisioned_support'] = not thick pools.append(pool) return pools
def test_get_share_capacity_info(self): mock_get_capacity = self.mock_object(self.driver, "_get_capacity_info") mock_get_capacity.return_value = fake.CAPACITY_VALUES expected_total_capacity_gb = na_utils.round_down(fake.TOTAL_BYTES / units.Gi, "0.01") expected_free_capacity_gb = na_utils.round_down(fake.AVAILABLE_BYTES / units.Gi, "0.01") expected_reserved_percentage = round(self.driver.configuration.reserved_percentage) result = self.driver._get_share_capacity_info(fake.NFS_SHARE) self.assertEqual(expected_total_capacity_gb, result["total_capacity_gb"]) self.assertEqual(expected_free_capacity_gb, result["free_capacity_gb"]) self.assertEqual(expected_reserved_percentage, round(result["reserved_percentage"]))
def _get_pool_stats(self, filter_function=None, goodness_function=None): """Retrieve pool (Data ONTAP flexvol) stats. Pool statistics are assembled from static driver capabilities, the Storage Service Catalog of flexvol attributes, and real-time capacity and controller utilization metrics. The pool name is the flexvol name. """ pools = [] ssc = self.ssc_library.get_ssc() if not ssc: return pools self.perf_library.update_performance_cache(ssc) for ssc_vol_name, ssc_vol_info in ssc.items(): pool = dict() # Add storage service catalog data pool.update(ssc_vol_info) # Add driver capabilities and config info pool['QoS_support'] = True pool['consistencygroup_support'] = True pool['reserved_percentage'] = self.reserved_percentage pool['max_over_subscription_ratio'] = ( self.max_over_subscription_ratio) # Add up-to-date capacity info capacity = self.zapi_client.get_flexvol_capacity( flexvol_name=ssc_vol_name) size_total_gb = capacity['size-total'] / units.Gi pool['total_capacity_gb'] = na_utils.round_down(size_total_gb) size_available_gb = capacity['size-available'] / units.Gi pool['free_capacity_gb'] = na_utils.round_down(size_available_gb) pool['provisioned_capacity_gb'] = round( pool['total_capacity_gb'] - pool['free_capacity_gb'], 2) # Add utilization data utilization = self.perf_library.get_node_utilization_for_pool( ssc_vol_name) pool['utilization'] = na_utils.round_down(utilization) pool['filter_function'] = filter_function pool['goodness_function'] = goodness_function pools.append(pool) return pools
def _get_pool_stats(self, filter_function=None, goodness_function=None): """Retrieve pool (Data ONTAP flexvol) stats. Pool statistics are assembled from static driver capabilities, the Storage Service Catalog of flexvol attributes, and real-time capacity and controller utilization metrics. The pool name is the flexvol name. """ pools = [] ssc = self.ssc_library.get_ssc() if not ssc: return pools self.perf_library.update_performance_cache(ssc) for ssc_vol_name, ssc_vol_info in ssc.items(): pool = dict() # Add storage service catalog data pool.update(ssc_vol_info) # Add driver capabilities and config info pool['QoS_support'] = True pool['consistencygroup_support'] = True pool['reserved_percentage'] = self.reserved_percentage pool['max_over_subscription_ratio'] = ( self.max_over_subscription_ratio) # Add up-to-date capacity info capacity = self.zapi_client.get_flexvol_capacity( flexvol_name=ssc_vol_name) size_total_gb = capacity['size-total'] / units.Gi pool['total_capacity_gb'] = na_utils.round_down(size_total_gb) size_available_gb = capacity['size-available'] / units.Gi pool['free_capacity_gb'] = na_utils.round_down(size_available_gb) pool['provisioned_capacity_gb'] = round( pool['total_capacity_gb'] - pool['free_capacity_gb'], 2) # Add utilization data utilization = self.perf_library.get_node_utilization_for_pool( ssc_vol_name) pool['utilization'] = na_utils.round_down(utilization) pool['filter_function'] = filter_function pool['goodness_function'] = goodness_function pools.append(pool) return pools
def test_round_down(self): self.assertAlmostEqual(na_utils.round_down(5.567), 5.56) self.assertAlmostEqual(na_utils.round_down(5.567, '0.00'), 5.56) self.assertAlmostEqual(na_utils.round_down(5.567, '0.0'), 5.5) self.assertAlmostEqual(na_utils.round_down(5.567, '0'), 5) self.assertAlmostEqual(na_utils.round_down(0, '0.00'), 0) self.assertAlmostEqual(na_utils.round_down(-5.567), -5.56) self.assertAlmostEqual(na_utils.round_down(-5.567, '0.00'), -5.56) self.assertAlmostEqual(na_utils.round_down(-5.567, '0.0'), -5.5) self.assertAlmostEqual(na_utils.round_down(-5.567, '0'), -5)
def test_round_down(self): self.assertAlmostEqual(na_utils.round_down(5.567), 5.56) self.assertAlmostEqual(na_utils.round_down(5.567, '0.00'), 5.56) self.assertAlmostEqual(na_utils.round_down(5.567, '0.0'), 5.5) self.assertAlmostEqual(na_utils.round_down(5.567, '0'), 5) self.assertAlmostEqual(na_utils.round_down(0, '0.00'), 0) self.assertAlmostEqual(na_utils.round_down(-5.567), -5.56) self.assertAlmostEqual(na_utils.round_down(-5.567, '0.00'), -5.56) self.assertAlmostEqual(na_utils.round_down(-5.567, '0.0'), -5.5) self.assertAlmostEqual(na_utils.round_down(-5.567, '0'), -5)
def _get_share_capacity_info(self, nfs_share): """Returns the share capacity metrics needed by the scheduler.""" capacity = dict() capacity['reserved_percentage'] = self.reserved_percentage capacity['max_over_subscription_ratio'] = ( self.max_over_subscription_ratio) total_size, total_available = self._get_capacity_info(nfs_share) capacity['total_capacity_gb'] = na_utils.round_down( total_size / units.Gi) capacity['free_capacity_gb'] = na_utils.round_down( total_available / units.Gi) return capacity
def _get_share_capacity_info(self, nfs_share): """Returns the share capacity metrics needed by the scheduler.""" capacity = dict() capacity['reserved_percentage'] = self.reserved_percentage capacity['max_over_subscription_ratio'] = ( self.max_over_subscription_ratio) total_size, total_available = self._get_capacity_info(nfs_share) capacity['total_capacity_gb'] = na_utils.round_down(total_size / units.Gi) capacity['free_capacity_gb'] = na_utils.round_down(total_available / units.Gi) return capacity
def _get_pool_stats(self, filter_function=None, goodness_function=None): """Retrieve pool (i.e. NFS share) stats info from SSC volumes.""" pools = [] self.perf_library.update_performance_cache() for nfs_share in self._mounted_shares: capacity = self._get_share_capacity_info(nfs_share) pool = dict() pool["pool_name"] = nfs_share pool["QoS_support"] = False pool.update(capacity) thick = not self.configuration.nfs_sparsed_volumes pool["thick_provisioning_support"] = thick pool["thin_provisioning_support"] = not thick utilization = self.perf_library.get_node_utilization() pool["utilization"] = na_utils.round_down(utilization, "0.01") pool["filter_function"] = filter_function pool["goodness_function"] = goodness_function pools.append(pool) return pools
def _get_pool_stats(self, filter_function=None, goodness_function=None): """Retrieve pool (i.e. NFS share) stats info from SSC volumes.""" pools = [] self.perf_library.update_performance_cache() for nfs_share in self._mounted_shares: capacity = self._get_share_capacity_info(nfs_share) pool = dict() pool['pool_name'] = nfs_share pool['QoS_support'] = False pool['multiattach'] = True pool.update(capacity) thick = not self.configuration.nfs_sparsed_volumes pool['thick_provisioning_support'] = thick pool['thin_provisioning_support'] = not thick utilization = self.perf_library.get_node_utilization() pool['utilization'] = na_utils.round_down(utilization, '0.01') pool['filter_function'] = filter_function pool['goodness_function'] = goodness_function pool['consistencygroup_support'] = True pools.append(pool) return pools
def _get_pool_stats(self): """Retrieve pool (Data ONTAP volume) stats info from SSC volumes.""" pools = [] if not self.ssc_vols: return pools for vol in self.ssc_vols['all']: pool = dict() pool['pool_name'] = vol.id['name'] pool['QoS_support'] = True pool['reserved_percentage'] = 0 # convert sizes to GB and de-rate by NetApp multiplier total = float(vol.space['size_total_bytes']) total /= self.configuration.netapp_size_multiplier total /= units.Gi pool['total_capacity_gb'] = na_utils.round_down(total, '0.01') free = float(vol.space['size_avl_bytes']) free /= self.configuration.netapp_size_multiplier free /= units.Gi pool['free_capacity_gb'] = na_utils.round_down(free, '0.01') pool['netapp_raid_type'] = vol.aggr['raid_type'] pool['netapp_disk_type'] = vol.aggr['disk_type'] mirrored = vol in self.ssc_vols['mirrored'] pool['netapp_mirrored'] = six.text_type(mirrored).lower() pool['netapp_unmirrored'] = six.text_type(not mirrored).lower() dedup = vol in self.ssc_vols['dedup'] pool['netapp_dedup'] = six.text_type(dedup).lower() pool['netapp_nodedup'] = six.text_type(not dedup).lower() compression = vol in self.ssc_vols['compression'] pool['netapp_compression'] = six.text_type(compression).lower() pool['netapp_nocompression'] = six.text_type( not compression).lower() thin = vol in self.ssc_vols['thin'] pool['netapp_thin_provisioned'] = six.text_type(thin).lower() pool['netapp_thick_provisioned'] = six.text_type(not thin).lower() pools.append(pool) return pools
def _get_pool_stats(self): """Retrieve pool (Data ONTAP volume) stats info from SSC volumes.""" pools = [] if not self.ssc_vols: return pools for vol in self.ssc_vols['all']: pool = dict() pool['pool_name'] = vol.id['name'] pool['QoS_support'] = False pool['reserved_percentage'] = 0 # convert sizes to GB and de-rate by NetApp multiplier total = float(vol.space['size_total_bytes']) total /= self.configuration.netapp_size_multiplier total /= units.Gi pool['total_capacity_gb'] = na_utils.round_down(total, '0.01') free = float(vol.space['size_avl_bytes']) free /= self.configuration.netapp_size_multiplier free /= units.Gi pool['free_capacity_gb'] = na_utils.round_down(free, '0.01') pool['netapp_raid_type'] = vol.aggr['raid_type'] pool['netapp_disk_type'] = vol.aggr['disk_type'] mirrored = vol in self.ssc_vols['mirrored'] pool['netapp_mirrored'] = six.text_type(mirrored).lower() pool['netapp_unmirrored'] = six.text_type(not mirrored).lower() dedup = vol in self.ssc_vols['dedup'] pool['netapp_dedup'] = six.text_type(dedup).lower() pool['netapp_nodedup'] = six.text_type(not dedup).lower() compression = vol in self.ssc_vols['compression'] pool['netapp_compression'] = six.text_type(compression).lower() pool['netapp_nocompression'] = six.text_type( not compression).lower() thin = vol in self.ssc_vols['thin'] pool['netapp_thin_provisioned'] = six.text_type(thin).lower() pool['netapp_thick_provisioned'] = six.text_type(not thin).lower() pools.append(pool) return pools
def _get_pool_stats(self): """Retrieve pool (i.e. Data ONTAP volume) stats info from volumes.""" pools = [] if not self.vols: return pools for vol in self.vols: # omit volumes not specified in the config volume_name = vol.get_child_content('name') if self.volume_list and volume_name not in self.volume_list: continue # omit root volume if volume_name == self.root_volume_name: continue # ensure good volume state state = vol.get_child_content('state') inconsistent = vol.get_child_content('is-inconsistent') invalid = vol.get_child_content('is-invalid') if (state != 'online' or inconsistent != 'false' or invalid != 'false'): continue pool = dict() pool['pool_name'] = volume_name pool['QoS_support'] = False pool['reserved_percentage'] = 0 # convert sizes to GB and de-rate by NetApp multiplier total = float(vol.get_child_content('size-total') or 0) total /= self.configuration.netapp_size_multiplier total /= units.Gi pool['total_capacity_gb'] = na_utils.round_down(total, '0.01') free = float(vol.get_child_content('size-available') or 0) free /= self.configuration.netapp_size_multiplier free /= units.Gi pool['free_capacity_gb'] = na_utils.round_down(free, '0.01') pools.append(pool) return pools
def _get_pool_stats(self): """Retrieve pool (i.e. Data ONTAP volume) stats info from volumes.""" pools = [] if not self.vols: return pools for vol in self.vols: # omit volumes not specified in the config volume_name = vol.get_child_content('name') if self.volume_list and volume_name not in self.volume_list: continue # omit root volume if volume_name == self.root_volume_name: continue # ensure good volume state state = vol.get_child_content('state') inconsistent = vol.get_child_content('is-inconsistent') invalid = vol.get_child_content('is-invalid') if (state != 'online' or inconsistent != 'false' or invalid != 'false'): continue pool = dict() pool['pool_name'] = volume_name pool['QoS_support'] = False pool['reserved_percentage'] = 0 # convert sizes to GB and de-rate by NetApp multiplier total = float(vol.get_child_content('size-total') or 0) total /= self.configuration.netapp_size_multiplier total /= units.Gi pool['total_capacity_gb'] = na_utils.round_down(total, '0.01') free = float(vol.get_child_content('size-available') or 0) free /= self.configuration.netapp_size_multiplier free /= units.Gi pool['free_capacity_gb'] = na_utils.round_down(free, '0.01') pools.append(pool) return pools
def test_get_share_capacity_info(self): mock_get_capacity = self.mock_object(self.driver, '_get_capacity_info') mock_get_capacity.return_value = fake.CAPACITY_VALUES expected_total_capacity_gb = na_utils.round_down( fake.TOTAL_BYTES / units.Gi, '0.01') expected_free_capacity_gb = (na_utils.round_down( fake.AVAILABLE_BYTES / units.Gi, '0.01')) expected_reserved_percentage = round( self.driver.configuration.reserved_percentage) result = self.driver._get_share_capacity_info(fake.NFS_SHARE) self.assertEqual(expected_total_capacity_gb, result['total_capacity_gb']) self.assertEqual(expected_free_capacity_gb, result['free_capacity_gb']) self.assertEqual(expected_reserved_percentage, round(result['reserved_percentage']))
def _get_pool_stats(self, filter_function=None, goodness_function=None): """Retrieve pool (Data ONTAP flexvol) stats. Pool statistics are assembled from static driver capabilities, the Storage Service Catalog of flexvol attributes, and real-time capacity and controller utilization metrics. The pool name is the NFS share path. """ pools = [] ssc = self.ssc_library.get_ssc() if not ssc: return pools # Get up-to-date node utilization metrics just once self.perf_library.update_performance_cache(ssc) # Get up-to-date aggregate capacities just once aggregates = self.ssc_library.get_ssc_aggregates() aggr_capacities = self.zapi_client.get_aggregate_capacities(aggregates) for ssc_vol_name, ssc_vol_info in ssc.items(): pool = dict() # Add storage service catalog data pool.update(ssc_vol_info) # Add driver capabilities and config info pool['QoS_support'] = True pool['consistencygroup_support'] = True pool['multiattach'] = True # Add up-to-date capacity info nfs_share = ssc_vol_info['pool_name'] capacity = self._get_share_capacity_info(nfs_share) pool.update(capacity) aggregate_name = ssc_vol_info.get('netapp_aggregate') aggr_capacity = aggr_capacities.get(aggregate_name, {}) pool['netapp_aggregate_used_percent'] = aggr_capacity.get( 'percent-used', 0) # Add utilization data utilization = self.perf_library.get_node_utilization_for_pool( ssc_vol_name) pool['utilization'] = na_utils.round_down(utilization) pool['filter_function'] = filter_function pool['goodness_function'] = goodness_function # Add replication capabilities/stats pool.update( self.get_replication_backend_stats(self.configuration)) pools.append(pool) return pools
def test_get_pool_stats(self, nfs_sparsed_volumes): self.driver.configuration.nfs_sparsed_volumes = nfs_sparsed_volumes thick = not nfs_sparsed_volumes total_capacity_gb = na_utils.round_down(fake.TOTAL_BYTES // units.Gi, '0.01') free_capacity_gb = na_utils.round_down( fake.AVAILABLE_BYTES // units.Gi, '0.01') provisioned_capacity_gb = total_capacity_gb - free_capacity_gb capacity = { 'reserved_percentage': fake.RESERVED_PERCENTAGE, 'max_over_subscription_ratio': fake.MAX_OVER_SUBSCRIPTION_RATIO, 'total_capacity_gb': total_capacity_gb, 'free_capacity_gb': free_capacity_gb, 'provisioned_capacity_gb': provisioned_capacity_gb, } self.mock_object(self.driver, '_get_share_capacity_info', return_value=capacity) self.mock_object(self.driver.perf_library, 'get_node_utilization', return_value=30.0) result = self.driver._get_pool_stats(filter_function='filter', goodness_function='goodness') expected = [{ 'pool_name': '192.168.99.24:/fake/export/path', 'QoS_support': False, 'consistencygroup_support': True, 'thick_provisioning_support': thick, 'thin_provisioning_support': not thick, 'free_capacity_gb': 12.0, 'total_capacity_gb': 4468.0, 'reserved_percentage': 7, 'max_over_subscription_ratio': 19.0, 'multiattach': False, 'provisioned_capacity_gb': 4456.0, 'utilization': 30.0, 'filter_function': 'filter', 'goodness_function': 'goodness' }] self.assertEqual(expected, result)
def test_get_share_capacity_info(self): mock_get_capacity = self.mock_object(self.driver, '_get_capacity_info') mock_get_capacity.return_value = fake.CAPACITY_VALUES expected_total_capacity_gb = na_utils.round_down( fake.TOTAL_BYTES / units.Gi, '0.01') expected_free_capacity_gb = (na_utils.round_down( fake.AVAILABLE_BYTES / units.Gi, '0.01')) expected_reserved_percentage = round( 100 * (1 - self.driver.configuration.nfs_used_ratio)) result = self.driver._get_share_capacity_info(fake.NFS_SHARE) self.assertEqual(expected_total_capacity_gb, result['total_capacity_gb']) self.assertEqual(expected_free_capacity_gb, result['free_capacity_gb']) self.assertEqual(expected_reserved_percentage, round(result['reserved_percentage']))
def _get_pool_stats(self, filter_function=None, goodness_function=None): """Retrieve pool (i.e. NFS share) stats info from SSC volumes.""" self.perf_library.update_performance_cache(self.ssc_vols.get( 'all', [])) pools = [] for nfs_share in self._mounted_shares: capacity = self._get_share_capacity_info(nfs_share) pool = dict() pool['pool_name'] = nfs_share pool['QoS_support'] = True pool.update(capacity) # add SSC content if available vol = self._get_vol_for_share(nfs_share) if vol and self.ssc_vols: pool['netapp_raid_type'] = vol.aggr['raid_type'] pool['netapp_disk_type'] = vol.aggr['disk_type'] mirrored = vol in self.ssc_vols['mirrored'] pool['netapp_mirrored'] = six.text_type(mirrored).lower() pool['netapp_unmirrored'] = six.text_type(not mirrored).lower() dedup = vol in self.ssc_vols['dedup'] pool['netapp_dedup'] = six.text_type(dedup).lower() pool['netapp_nodedup'] = six.text_type(not dedup).lower() compression = vol in self.ssc_vols['compression'] pool['netapp_compression'] = six.text_type(compression).lower() pool['netapp_nocompression'] = six.text_type( not compression).lower() flexvol_thin = vol in self.ssc_vols['thin'] pool['netapp_thin_provisioned'] = six.text_type( flexvol_thin).lower() pool['netapp_thick_provisioned'] = six.text_type( not flexvol_thin).lower() thick = (not flexvol_thin and not self.configuration.nfs_sparsed_volumes) pool['thick_provisioning_support'] = thick pool['thin_provisioning_support'] = not thick utilization = self.perf_library.get_node_utilization_for_pool( vol.id['name']) pool['utilization'] = na_utils.round_down(utilization, '0.01') pool['filter_function'] = filter_function pool['goodness_function'] = goodness_function pools.append(pool) return pools
def _get_pool_stats(self, filter_function=None, goodness_function=None): """Retrieve pool (i.e. NFS share) stats info from SSC volumes.""" self.perf_library.update_performance_cache( self.ssc_vols.get('all', [])) pools = [] for nfs_share in self._mounted_shares: capacity = self._get_share_capacity_info(nfs_share) pool = dict() pool['pool_name'] = nfs_share pool['QoS_support'] = True pool.update(capacity) # add SSC content if available vol = self._get_vol_for_share(nfs_share) if vol and self.ssc_vols: pool['netapp_raid_type'] = vol.aggr['raid_type'] pool['netapp_disk_type'] = vol.aggr['disk_type'] mirrored = vol in self.ssc_vols['mirrored'] pool['netapp_mirrored'] = six.text_type(mirrored).lower() pool['netapp_unmirrored'] = six.text_type(not mirrored).lower() dedup = vol in self.ssc_vols['dedup'] pool['netapp_dedup'] = six.text_type(dedup).lower() pool['netapp_nodedup'] = six.text_type(not dedup).lower() compression = vol in self.ssc_vols['compression'] pool['netapp_compression'] = six.text_type(compression).lower() pool['netapp_nocompression'] = six.text_type( not compression).lower() flexvol_thin = vol in self.ssc_vols['thin'] pool['netapp_thin_provisioned'] = six.text_type( flexvol_thin).lower() pool['netapp_thick_provisioned'] = six.text_type( not flexvol_thin).lower() thick = (not flexvol_thin and not self.configuration.nfs_sparsed_volumes) pool['thick_provisioning_support'] = thick pool['thin_provisioning_support'] = not thick utilization = self.perf_library.get_node_utilization_for_pool( vol.id['name']) pool['utilization'] = na_utils.round_down(utilization, '0.01') pool['filter_function'] = filter_function pool['goodness_function'] = goodness_function pools.append(pool) return pools
def test_get_pool_stats(self, nfs_sparsed_volumes): self.driver.configuration.nfs_sparsed_volumes = nfs_sparsed_volumes thick = not nfs_sparsed_volumes total_capacity_gb = na_utils.round_down( fake.TOTAL_BYTES // units.Gi, '0.01') free_capacity_gb = na_utils.round_down( fake.AVAILABLE_BYTES // units.Gi, '0.01') provisioned_capacity_gb = total_capacity_gb - free_capacity_gb capacity = { 'reserved_percentage': fake.RESERVED_PERCENTAGE, 'max_over_subscription_ratio': fake.MAX_OVER_SUBSCRIPTION_RATIO, 'total_capacity_gb': total_capacity_gb, 'free_capacity_gb': free_capacity_gb, 'provisioned_capacity_gb': provisioned_capacity_gb, } self.mock_object(self.driver, '_get_share_capacity_info', return_value=capacity) self.mock_object(self.driver.perf_library, 'get_node_utilization', return_value=30.0) result = self.driver._get_pool_stats(filter_function='filter', goodness_function='goodness') expected = [{'pool_name': '192.168.99.24:/fake/export/path', 'QoS_support': False, 'consistencygroup_support': True, 'thick_provisioning_support': thick, 'thin_provisioning_support': not thick, 'free_capacity_gb': 12.0, 'total_capacity_gb': 4468.0, 'reserved_percentage': 7, 'max_over_subscription_ratio': 19.0, 'multiattach': False, 'provisioned_capacity_gb': 4456.0, 'utilization': 30.0, 'filter_function': 'filter', 'goodness_function': 'goodness'}] self.assertEqual(expected, result)
def _get_pool_stats(self, filter_function=None, goodness_function=None): """Retrieve pool (Data ONTAP flexvol) stats. Pool statistics are assembled from static driver capabilities, the Storage Service Catalog of flexvol attributes, and real-time capacity and controller utilization metrics. The pool name is the NFS share path. """ pools = [] ssc = self.ssc_library.get_ssc() if not ssc: return pools self.perf_library.update_performance_cache(ssc) for ssc_vol_name, ssc_vol_info in ssc.items(): pool = dict() # Add storage service catalog data pool.update(ssc_vol_info) # Add driver capabilities and config info pool['QoS_support'] = True # Add up-to-date capacity info nfs_share = ssc_vol_info['pool_name'] capacity = self._get_share_capacity_info(nfs_share) pool.update(capacity) # Add utilization data utilization = self.perf_library.get_node_utilization_for_pool( ssc_vol_name) pool['utilization'] = na_utils.round_down(utilization) pool['filter_function'] = filter_function pool['goodness_function'] = goodness_function pools.append(pool) return pools
def _get_pool_stats(self, filter_function=None, goodness_function=None): """Retrieve pool (Data ONTAP flexvol) stats. Pool statistics are assembled from static driver capabilities, the Storage Service Catalog of flexvol attributes, and real-time capacity and controller utilization metrics. The pool name is the NFS share path. """ pools = [] ssc = self.ssc_library.get_ssc() if not ssc: return pools self.perf_library.update_performance_cache(ssc) for ssc_vol_name, ssc_vol_info in ssc.items(): pool = dict() # Add storage service catalog data pool.update(ssc_vol_info) # Add driver capabilities and config info pool['QoS_support'] = True # Add up-to-date capacity info nfs_share = ssc_vol_info['pool_name'] capacity = self._get_share_capacity_info(nfs_share) pool.update(capacity) # Add utilization data utilization = self.perf_library.get_node_utilization_for_pool( ssc_vol_name) pool['utilization'] = na_utils.round_down(utilization) pool['filter_function'] = filter_function pool['goodness_function'] = goodness_function pools.append(pool) return pools
def _get_pool_stats(self, filter_function=None, goodness_function=None): """Retrieve pool (Data ONTAP flexvol) stats. Pool statistics are assembled from static driver capabilities, the Storage Service Catalog of flexvol attributes, and real-time capacity and controller utilization metrics. The pool name is the flexvol name. """ pools = [] ssc = self.ssc_library.get_ssc() if not ssc: return pools # Utilization and performance metrics require cluster-scoped # credentials if self.using_cluster_credentials: # Get up-to-date node utilization metrics just once self.perf_library.update_performance_cache(ssc) # Get up-to-date aggregate capacities just once aggregates = self.ssc_library.get_ssc_aggregates() aggr_capacities = self.zapi_client.get_aggregate_capacities( aggregates) else: aggr_capacities = {} for ssc_vol_name, ssc_vol_info in ssc.items(): pool = dict() # Add storage service catalog data pool.update(ssc_vol_info) # Add driver capabilities and config info pool['QoS_support'] = self.using_cluster_credentials pool['multiattach'] = True pool['online_extend_support'] = False pool['consistencygroup_support'] = True pool['consistent_group_snapshot_enabled'] = True pool['reserved_percentage'] = self.reserved_percentage pool['max_over_subscription_ratio'] = ( self.max_over_subscription_ratio) # Add up-to-date capacity info capacity = self.zapi_client.get_flexvol_capacity( flexvol_name=ssc_vol_name) size_total_gb = capacity['size-total'] / units.Gi pool['total_capacity_gb'] = na_utils.round_down(size_total_gb) size_available_gb = capacity['size-available'] / units.Gi pool['free_capacity_gb'] = na_utils.round_down(size_available_gb) if self.using_cluster_credentials: dedupe_used = self.zapi_client.get_flexvol_dedupe_used_percent( ssc_vol_name) else: dedupe_used = 0.0 pool['netapp_dedupe_used_percent'] = na_utils.round_down( dedupe_used) aggregate_name = ssc_vol_info.get('netapp_aggregate') aggr_capacity = aggr_capacities.get(aggregate_name, {}) pool['netapp_aggregate_used_percent'] = aggr_capacity.get( 'percent-used', 0) # Add utilization data utilization = self.perf_library.get_node_utilization_for_pool( ssc_vol_name) pool['utilization'] = na_utils.round_down(utilization) pool['filter_function'] = filter_function pool['goodness_function'] = goodness_function # Add replication capabilities/stats pool.update(self.get_replication_backend_stats(self.configuration)) pools.append(pool) return pools
def test_get_pool_stats(self): ssc = { 'vola': { 'pool_name': '10.10.10.10:/vola', 'thick_provisioning_support': True, 'thin_provisioning_support': False, 'netapp_thin_provisioned': 'false', 'netapp_compression': 'false', 'netapp_mirrored': 'false', 'netapp_dedup': 'true', 'aggregate': 'aggr1', 'netapp_raid_type': 'raid_dp', 'netapp_disk_type': 'SSD', }, } mock_get_ssc = self.mock_object(self.driver.ssc_library, 'get_ssc', mock.Mock(return_value=ssc)) total_capacity_gb = na_utils.round_down( fake.TOTAL_BYTES // units.Gi, '0.01') free_capacity_gb = na_utils.round_down( fake.AVAILABLE_BYTES // units.Gi, '0.01') provisioned_capacity_gb = total_capacity_gb - free_capacity_gb capacity = { 'reserved_percentage': fake.RESERVED_PERCENTAGE, 'max_over_subscription_ratio': fake.MAX_OVER_SUBSCRIPTION_RATIO, 'total_capacity_gb': total_capacity_gb, 'free_capacity_gb': free_capacity_gb, 'provisioned_capacity_gb': provisioned_capacity_gb, } self.mock_object(self.driver, '_get_share_capacity_info', mock.Mock(return_value=capacity)) self.driver.perf_library.get_node_utilization_for_pool = ( mock.Mock(return_value=30.0)) result = self.driver._get_pool_stats(filter_function='filter', goodness_function='goodness') expected = [{ 'pool_name': '10.10.10.10:/vola', 'QoS_support': True, 'reserved_percentage': fake.RESERVED_PERCENTAGE, 'max_over_subscription_ratio': fake.MAX_OVER_SUBSCRIPTION_RATIO, 'total_capacity_gb': total_capacity_gb, 'free_capacity_gb': free_capacity_gb, 'provisioned_capacity_gb': provisioned_capacity_gb, 'utilization': 30.0, 'filter_function': 'filter', 'goodness_function': 'goodness', 'thick_provisioning_support': True, 'thin_provisioning_support': False, 'netapp_thin_provisioned': 'false', 'netapp_compression': 'false', 'netapp_mirrored': 'false', 'netapp_dedup': 'true', 'aggregate': 'aggr1', 'netapp_raid_type': 'raid_dp', 'netapp_disk_type': 'SSD', }] self.assertEqual(expected, result) mock_get_ssc.assert_called_once_with()
export_path = share.split(':')[1] else: raise exception.InvalidInput( 'A volume ID or share was not specified.') return host_ip, export_path def _get_share_capacity_info(self, nfs_share): """Returns the share capacity metrics needed by the scheduler.""" <<<<<<< HEAD capacity = dict() capacity['reserved_percentage'] = self.reserved_percentage capacity['max_over_subscription_ratio'] = ( self.max_over_subscription_ratio) total_size, total_available = self._get_capacity_info(nfs_share) capacity['total_capacity_gb'] = na_utils.round_down( total_size / units.Gi, '0.01') capacity['free_capacity_gb'] = na_utils.round_down( total_available / units.Gi, '0.01') capacity['provisioned_capacity_gb'] = (round( capacity['total_capacity_gb'] - capacity['free_capacity_gb'], 2)) ======= used_ratio = self.configuration.nfs_used_ratio oversub_ratio = self.configuration.nfs_oversub_ratio # The scheduler's capacity filter will reduce the amount of # free space that we report to it by the reserved percentage. reserved_ratio = 1 - used_ratio reserved_percentage = round(100 * reserved_ratio) total_size, total_available = self._get_capacity_info(nfs_share)
def _get_pool_stats(self, filter_function=None, goodness_function=None): """Retrieve pool (Data ONTAP volume) stats info from SSC volumes.""" pools = [] if not self.ssc_vols: return pools filtered_pools = self._get_filtered_pools() self.perf_library.update_performance_cache(filtered_pools) for vol in filtered_pools: pool_name = vol.id['name'] pool = dict() pool['pool_name'] = pool_name pool['QoS_support'] = True pool['reserved_percentage'] = ( self.reserved_percentage) pool['max_over_subscription_ratio'] = ( self.max_over_subscription_ratio) # Get capacity info and convert to GB capacity = self.zapi_client.get_flexvol_capacity( flexvol_name=pool_name) size_total_gb = capacity['size-total'] / units.Gi pool['total_capacity_gb'] = na_utils.round_down(size_total_gb) size_available_gb = capacity['size-available'] / units.Gi pool['free_capacity_gb'] = na_utils.round_down(size_available_gb) pool['provisioned_capacity_gb'] = (round( pool['total_capacity_gb'] - pool['free_capacity_gb'], 2)) pool['netapp_raid_type'] = vol.aggr['raid_type'] pool['netapp_disk_type'] = vol.aggr['disk_type'] mirrored = vol in self.ssc_vols['mirrored'] pool['netapp_mirrored'] = six.text_type(mirrored).lower() pool['netapp_unmirrored'] = six.text_type(not mirrored).lower() dedup = vol in self.ssc_vols['dedup'] pool['netapp_dedup'] = six.text_type(dedup).lower() pool['netapp_nodedup'] = six.text_type(not dedup).lower() compression = vol in self.ssc_vols['compression'] pool['netapp_compression'] = six.text_type(compression).lower() pool['netapp_nocompression'] = six.text_type( not compression).lower() thin = vol in self.ssc_vols['thin'] pool['netapp_thin_provisioned'] = six.text_type(thin).lower() pool['netapp_thick_provisioned'] = six.text_type(not thin).lower() thick = (not thin and self.configuration.netapp_lun_space_reservation == 'enabled') pool['thick_provisioning_support'] = thick pool['thin_provisioning_support'] = not thick utilization = self.perf_library.get_node_utilization_for_pool( pool_name) pool['utilization'] = na_utils.round_down(utilization, '0.01') pool['filter_function'] = filter_function pool['goodness_function'] = goodness_function pool['consistencygroup_support'] = True pools.append(pool) return pools
def _get_pool_stats(self, filter_function=None, goodness_function=None): """Retrieve pool (Data ONTAP flexvol) stats. Pool statistics are assembled from static driver capabilities, the Storage Service Catalog of flexvol attributes, and real-time capacity and controller utilization metrics. The pool name is the flexvol name. """ pools = [] ssc = self.ssc_library.get_ssc() if not ssc: return pools # Utilization and performance metrics require cluster-scoped # credentials if self.using_cluster_credentials: # Get up-to-date node utilization metrics just once self.perf_library.update_performance_cache(ssc) # Get up-to-date aggregate capacities just once aggregates = self.ssc_library.get_ssc_aggregates() aggr_capacities = self.zapi_client.get_aggregate_capacities( aggregates) else: aggr_capacities = {} for ssc_vol_name, ssc_vol_info in ssc.items(): pool = dict() # Add storage service catalog data pool.update(ssc_vol_info) # Add driver capabilities and config info pool['QoS_support'] = self.using_cluster_credentials pool['multiattach'] = False pool['consistencygroup_support'] = True pool['consistent_group_snapshot_enabled'] = True pool['reserved_percentage'] = self.reserved_percentage pool['max_over_subscription_ratio'] = ( self.max_over_subscription_ratio) # Add up-to-date capacity info capacity = self.zapi_client.get_flexvol_capacity( flexvol_name=ssc_vol_name) size_total_gb = capacity['size-total'] / units.Gi pool['total_capacity_gb'] = na_utils.round_down(size_total_gb) size_available_gb = capacity['size-available'] / units.Gi pool['free_capacity_gb'] = na_utils.round_down(size_available_gb) if self.using_cluster_credentials: dedupe_used = self.zapi_client.get_flexvol_dedupe_used_percent( ssc_vol_name) else: dedupe_used = 0.0 pool['netapp_dedupe_used_percent'] = na_utils.round_down( dedupe_used) aggregate_name = ssc_vol_info.get('netapp_aggregate') aggr_capacity = aggr_capacities.get(aggregate_name, {}) pool['netapp_aggregate_used_percent'] = aggr_capacity.get( 'percent-used', 0) # Add utilization data utilization = self.perf_library.get_node_utilization_for_pool( ssc_vol_name) pool['utilization'] = na_utils.round_down(utilization) pool['filter_function'] = filter_function pool['goodness_function'] = goodness_function # Add replication capabilities/stats pool.update( self.get_replication_backend_stats(self.configuration)) pools.append(pool) return pools
def test_get_pool_stats(self, thin, nfs_sparsed_volumes): class test_volume(object): pass test_volume = test_volume() test_volume.id = {'vserver': 'openstack', 'name': 'vola'} test_volume.aggr = { 'disk_type': 'SSD', 'ha_policy': 'cfo', 'junction': '/vola', 'name': 'aggr1', 'raid_type': 'raiddp', } test_volume.export = {'path': fake.NFS_SHARE} test_volume.sis = {'dedup': False, 'compression': False} test_volume.state = { 'status': 'online', 'vserver_root': False, 'junction_active': True, } test_volume.qos = {'qos_policy_group': None} ssc_map = { 'mirrored': {}, 'dedup': {}, 'compression': {}, 'thin': {test_volume if thin else None}, 'all': [test_volume], } self.driver.ssc_vols = ssc_map self.driver.configuration.nfs_sparsed_volumes = nfs_sparsed_volumes netapp_thin = 'true' if thin else 'false' netapp_thick = 'false' if thin else 'true' thick = not thin and not nfs_sparsed_volumes total_capacity_gb = na_utils.round_down(fake.TOTAL_BYTES // units.Gi, '0.01') free_capacity_gb = na_utils.round_down( fake.AVAILABLE_BYTES // units.Gi, '0.01') provisioned_capacity_gb = total_capacity_gb - free_capacity_gb capacity = { 'reserved_percentage': fake.RESERVED_PERCENTAGE, 'max_over_subscription_ratio': fake.MAX_OVER_SUBSCRIPTION_RATIO, 'total_capacity_gb': total_capacity_gb, 'free_capacity_gb': free_capacity_gb, 'provisioned_capacity_gb': provisioned_capacity_gb, } self.mock_object(self.driver, '_get_share_capacity_info', mock.Mock(return_value=capacity)) self.driver.perf_library.get_node_utilization_for_pool = (mock.Mock( return_value=30.0)) result = self.driver._get_pool_stats(filter_function='filter', goodness_function='goodness') expected = [{ 'pool_name': '192.168.99.24:/fake/export/path', 'netapp_unmirrored': 'true', 'QoS_support': True, 'thick_provisioning_support': thick, 'netapp_thick_provisioned': netapp_thick, 'netapp_nocompression': 'true', 'thin_provisioning_support': not thick, 'free_capacity_gb': 12.0, 'netapp_thin_provisioned': netapp_thin, 'total_capacity_gb': 4468.0, 'netapp_compression': 'false', 'netapp_mirrored': 'false', 'netapp_dedup': 'false', 'reserved_percentage': 7, 'netapp_raid_type': 'raiddp', 'netapp_disk_type': 'SSD', 'netapp_nodedup': 'true', 'max_over_subscription_ratio': 19.0, 'provisioned_capacity_gb': 4456.0, 'utilization': 30.0, 'filter_function': 'filter', 'goodness_function': 'goodness' }] self.assertEqual(expected, result)
def test_get_pool_stats(self, thin, nfs_sparsed_volumes): class test_volume(object): pass test_volume = test_volume() test_volume.id = {'vserver': 'openstack', 'name': 'vola'} test_volume.aggr = { 'disk_type': 'SSD', 'ha_policy': 'cfo', 'junction': '/vola', 'name': 'aggr1', 'raid_type': 'raiddp', } test_volume.export = {'path': fake.NFS_SHARE} test_volume.sis = {'dedup': False, 'compression': False} test_volume.state = { 'status': 'online', 'vserver_root': False, 'junction_active': True, } test_volume.qos = {'qos_policy_group': None} ssc_map = { 'mirrored': {}, 'dedup': {}, 'compression': {}, 'thin': {test_volume if thin else None}, 'all': [test_volume], } self.driver.ssc_vols = ssc_map self.driver.configuration.nfs_sparsed_volumes = nfs_sparsed_volumes netapp_thin = 'true' if thin else 'false' netapp_thick = 'false' if thin else 'true' thick = not thin and not nfs_sparsed_volumes total_capacity_gb = na_utils.round_down( fake.TOTAL_BYTES / units.Gi, '0.01') free_capacity_gb = na_utils.round_down( fake.AVAILABLE_BYTES / units.Gi, '0.01') provisioned_capacity_gb = total_capacity_gb - free_capacity_gb capacity = { 'reserved_percentage': fake.RESERVED_PERCENTAGE, 'max_over_subscription_ratio': fake.MAX_OVER_SUBSCRIPTION_RATIO, 'total_capacity_gb': total_capacity_gb, 'free_capacity_gb': free_capacity_gb, 'provisioned_capacity_gb': provisioned_capacity_gb, } self.mock_object(self.driver, '_get_share_capacity_info', mock.Mock(return_value=capacity)) result = self.driver._get_pool_stats() expected = [{'pool_name': '192.168.99.24:/fake/export/path', 'netapp_unmirrored': 'true', 'QoS_support': True, 'thick_provisioning_support': thick, 'netapp_thick_provisioned': netapp_thick, 'netapp_nocompression': 'true', 'thin_provisioning_support': not thick, 'free_capacity_gb': 12.0, 'netapp_thin_provisioned': netapp_thin, 'total_capacity_gb': 4468.0, 'netapp_compression': 'false', 'netapp_mirrored': 'false', 'netapp_dedup': 'false', 'reserved_percentage': 7, 'netapp_raid_type': 'raiddp', 'netapp_disk_type': 'SSD', 'netapp_nodedup': 'true', 'max_over_subscription_ratio': 19.0, 'provisioned_capacity_gb': 4456.0}] self.assertEqual(expected, result)
for nfs_share in self._mounted_shares: capacity = self._get_share_capacity_info(nfs_share) pool = dict() pool['pool_name'] = nfs_share pool['QoS_support'] = False pool.update(capacity) <<<<<<< HEAD thick = not self.configuration.nfs_sparsed_volumes pool['thick_provisioning_support'] = thick pool['thin_provisioning_support'] = not thick utilization = self.perf_library.get_node_utilization() pool['utilization'] = na_utils.round_down(utilization, '0.01') pool['filter_function'] = filter_function pool['goodness_function'] = goodness_function ======= >>>>>>> refs/remotes/openstack/stable/kilo pools.append(pool) return pools def _shortlist_del_eligible_files(self, share, old_files): """Prepares list of eligible files to be deleted from cache.""" file_list = [] (_, export_path) = self._get_export_ip_path(share=share) exported_volume = self.zapi_client.get_actual_path_for_export( export_path)
def test_get_pool_stats(self, thin, nfs_sparsed_volumes): class test_volume(object): pass test_volume = test_volume() test_volume.id = {"vserver": "openstack", "name": "vola"} test_volume.aggr = { "disk_type": "SSD", "ha_policy": "cfo", "junction": "/vola", "name": "aggr1", "raid_type": "raiddp", } test_volume.export = {"path": fake.NFS_SHARE} test_volume.sis = {"dedup": False, "compression": False} test_volume.state = {"status": "online", "vserver_root": False, "junction_active": True} test_volume.qos = {"qos_policy_group": None} ssc_map = { "mirrored": {}, "dedup": {}, "compression": {}, "thin": {test_volume if thin else None}, "all": [test_volume], } self.driver.ssc_vols = ssc_map self.driver.configuration.nfs_sparsed_volumes = nfs_sparsed_volumes netapp_thin = "true" if thin else "false" netapp_thick = "false" if thin else "true" thick = not thin and not nfs_sparsed_volumes total_capacity_gb = na_utils.round_down(fake.TOTAL_BYTES / units.Gi, "0.01") free_capacity_gb = na_utils.round_down(fake.AVAILABLE_BYTES / units.Gi, "0.01") provisioned_capacity_gb = total_capacity_gb - free_capacity_gb capacity = { "reserved_percentage": fake.RESERVED_PERCENTAGE, "max_over_subscription_ratio": fake.MAX_OVER_SUBSCRIPTION_RATIO, "total_capacity_gb": total_capacity_gb, "free_capacity_gb": free_capacity_gb, "provisioned_capacity_gb": provisioned_capacity_gb, } self.mock_object(self.driver, "_get_share_capacity_info", mock.Mock(return_value=capacity)) result = self.driver._get_pool_stats() expected = [ { "pool_name": "192.168.99.24:/fake/export/path", "netapp_unmirrored": "true", "QoS_support": True, "thick_provisioning_support": thick, "netapp_thick_provisioned": netapp_thick, "netapp_nocompression": "true", "thin_provisioning_support": not thick, "free_capacity_gb": 12.0, "netapp_thin_provisioned": netapp_thin, "total_capacity_gb": 4468.0, "netapp_compression": "false", "netapp_mirrored": "false", "netapp_dedup": "false", "reserved_percentage": 7, "netapp_raid_type": "raiddp", "netapp_disk_type": "SSD", "netapp_nodedup": "true", "reserved_percentage": 7, "max_over_subscription_ratio": 19.0, "provisioned_capacity_gb": 4456.0, } ] self.assertEqual(expected, result)
def test_get_pool_stats(self): self.driver.zapi_client = mock.Mock() ssc = { 'vola': { 'pool_name': '10.10.10.10:/vola', 'thick_provisioning_support': True, 'thin_provisioning_support': False, 'netapp_thin_provisioned': 'false', 'netapp_compression': 'false', 'netapp_mirrored': 'false', 'netapp_dedup': 'true', 'aggregate': 'aggr1', 'netapp_raid_type': 'raid_dp', 'netapp_disk_type': 'SSD', }, } mock_get_ssc = self.mock_object(self.driver.ssc_library, 'get_ssc', mock.Mock(return_value=ssc)) mock_get_aggrs = self.mock_object(self.driver.ssc_library, 'get_ssc_aggregates', mock.Mock(return_value=['aggr1'])) total_capacity_gb = na_utils.round_down( fake.TOTAL_BYTES // units.Gi, '0.01') free_capacity_gb = na_utils.round_down( fake.AVAILABLE_BYTES // units.Gi, '0.01') provisioned_capacity_gb = total_capacity_gb - free_capacity_gb capacity = { 'reserved_percentage': fake.RESERVED_PERCENTAGE, 'max_over_subscription_ratio': fake.MAX_OVER_SUBSCRIPTION_RATIO, 'total_capacity_gb': total_capacity_gb, 'free_capacity_gb': free_capacity_gb, 'provisioned_capacity_gb': provisioned_capacity_gb, } self.mock_object(self.driver, '_get_share_capacity_info', mock.Mock(return_value=capacity)) aggr_capacities = { 'aggr1': { 'percent-used': 45, 'size-available': 59055800320.0, 'size-total': 107374182400.0, }, } mock_get_aggr_capacities = self.mock_object( self.driver.zapi_client, 'get_aggregate_capacities', mock.Mock(return_value=aggr_capacities)) self.driver.perf_library.get_node_utilization_for_pool = ( mock.Mock(return_value=30.0)) result = self.driver._get_pool_stats(filter_function='filter', goodness_function='goodness') expected = [{ 'pool_name': '10.10.10.10:/vola', 'QoS_support': True, 'reserved_percentage': fake.RESERVED_PERCENTAGE, 'max_over_subscription_ratio': fake.MAX_OVER_SUBSCRIPTION_RATIO, 'total_capacity_gb': total_capacity_gb, 'free_capacity_gb': free_capacity_gb, 'provisioned_capacity_gb': provisioned_capacity_gb, 'aggregate_used_percent': 45, 'utilization': 30.0, 'filter_function': 'filter', 'goodness_function': 'goodness', 'thick_provisioning_support': True, 'thin_provisioning_support': False, 'netapp_thin_provisioned': 'false', 'netapp_compression': 'false', 'netapp_mirrored': 'false', 'netapp_dedup': 'true', 'aggregate': 'aggr1', 'netapp_raid_type': 'raid_dp', 'netapp_disk_type': 'SSD', }] self.assertEqual(expected, result) mock_get_ssc.assert_called_once_with() mock_get_aggrs.assert_called_once_with() mock_get_aggr_capacities.assert_called_once_with(['aggr1'])
def _get_pool_stats(self, filter_function=None, goodness_function=None): """Retrieve pool (Data ONTAP flexvol) stats. Pool statistics are assembled from static driver capabilities, the Storage Service Catalog of flexvol attributes, and real-time capacity and controller utilization metrics. The pool name is the flexvol name. """ pools = [] ssc = self.ssc_library.get_ssc() if not ssc: return pools # Get up-to-date node utilization metrics just once self.perf_library.update_performance_cache(ssc) # Get up-to-date aggregate capacities just once aggregates = self.ssc_library.get_ssc_aggregates() aggr_capacities = self.zapi_client.get_aggregate_capacities(aggregates) for ssc_vol_name, ssc_vol_info in ssc.items(): pool = dict() # Add storage service catalog data pool.update(ssc_vol_info) # Add driver capabilities and config info pool["QoS_support"] = True pool["multiattach"] = True pool["consistencygroup_support"] = True pool["reserved_percentage"] = self.reserved_percentage pool["max_over_subscription_ratio"] = self.max_over_subscription_ratio # Add up-to-date capacity info capacity = self.zapi_client.get_flexvol_capacity(flexvol_name=ssc_vol_name) size_total_gb = capacity["size-total"] / units.Gi pool["total_capacity_gb"] = na_utils.round_down(size_total_gb) size_available_gb = capacity["size-available"] / units.Gi pool["free_capacity_gb"] = na_utils.round_down(size_available_gb) pool["provisioned_capacity_gb"] = round(pool["total_capacity_gb"] - pool["free_capacity_gb"], 2) aggregate_name = ssc_vol_info.get("netapp_aggregate") aggr_capacity = aggr_capacities.get(aggregate_name, {}) pool["netapp_aggregate_used_percent"] = aggr_capacity.get("percent-used", 0) # Add utilization data utilization = self.perf_library.get_node_utilization_for_pool(ssc_vol_name) pool["utilization"] = na_utils.round_down(utilization) pool["filter_function"] = filter_function pool["goodness_function"] = goodness_function # Add replication capabilities/stats pool.update(self.get_replication_backend_stats(self.configuration)) pools.append(pool) return pools
def _get_pool_stats(self, filter_function=None, goodness_function=None): """Retrieve pool (Data ONTAP flexvol) stats. Pool statistics are assembled from static driver capabilities, the Storage Service Catalog of flexvol attributes, and real-time capacity and controller utilization metrics. The pool name is the NFS share path. """ pools = [] ssc = self.ssc_library.get_ssc() if not ssc: return pools # Utilization and performance metrics require cluster-scoped # credentials if self.using_cluster_credentials: # Get up-to-date node utilization metrics just once self.perf_library.update_performance_cache(ssc) # Get up-to-date aggregate capacities just once aggregates = self.ssc_library.get_ssc_aggregates() aggr_capacities = self.zapi_client.get_aggregate_capacities( aggregates) else: aggr_capacities = {} for ssc_vol_name, ssc_vol_info in ssc.items(): pool = dict() # Add storage service catalog data pool.update(ssc_vol_info) # Add driver capabilities and config info pool['QoS_support'] = self.using_cluster_credentials pool['consistencygroup_support'] = True pool['consistent_group_snapshot_enabled'] = True pool['multiattach'] = True pool['online_extend_support'] = False is_flexgroup = ssc_vol_info.get('netapp_is_flexgroup') == 'true' if is_flexgroup: pool['consistencygroup_support'] = False pool['consistent_group_snapshot_enabled'] = False pool['multiattach'] = False # Add up-to-date capacity info nfs_share = ssc_vol_info['pool_name'] capacity = self._get_share_capacity_info(nfs_share) pool.update(capacity) if self.using_cluster_credentials and not is_flexgroup: dedupe_used = self.zapi_client.get_flexvol_dedupe_used_percent( ssc_vol_name) else: dedupe_used = 0.0 pool['netapp_dedupe_used_percent'] = na_utils.round_down( dedupe_used) aggregate_name = ssc_vol_info.get('netapp_aggregate') aggr_used = 0 if isinstance(aggregate_name, list): # For FlexGroup, the aggregate percentage can be seen as the # average of all aggregates. aggr_used_total = 0 aggr_num = 0 for aggr in aggregate_name: aggr_capacity = aggr_capacities.get(aggr, {}) aggr_used_total += aggr_capacity.get('percent-used', 0) aggr_num += 1 if aggr_num: aggr_used = aggr_used_total / aggr_num else: aggr_capacity = aggr_capacities.get(aggregate_name, {}) aggr_used = aggr_capacity.get('percent-used', 0) pool['netapp_aggregate_used_percent'] = aggr_used # Add utilization data utilization = self.perf_library.get_node_utilization_for_pool( ssc_vol_name) pool['utilization'] = na_utils.round_down(utilization) pool['filter_function'] = filter_function pool['goodness_function'] = goodness_function # Add replication capabilities/stats pool.update(self.get_replication_backend_stats(self.configuration)) pools.append(pool) return pools
def _get_pool_stats(self, filter_function=None, goodness_function=None): """Retrieve pool (Data ONTAP volume) stats info from SSC volumes.""" pools = [] if not self.ssc_vols: return pools filtered_pools = self._get_filtered_pools() self.perf_library.update_performance_cache(filtered_pools) for vol in filtered_pools: pool_name = vol.id["name"] pool = dict() pool["pool_name"] = pool_name pool["QoS_support"] = True pool["reserved_percentage"] = self.reserved_percentage pool["max_over_subscription_ratio"] = self.max_over_subscription_ratio # convert sizes to GB total = float(vol.space["size_total_bytes"]) total /= units.Gi pool["total_capacity_gb"] = na_utils.round_down(total, "0.01") free = float(vol.space["size_avl_bytes"]) free /= units.Gi pool["free_capacity_gb"] = na_utils.round_down(free, "0.01") pool["provisioned_capacity_gb"] = round(pool["total_capacity_gb"] - pool["free_capacity_gb"], 2) pool["netapp_raid_type"] = vol.aggr["raid_type"] pool["netapp_disk_type"] = vol.aggr["disk_type"] mirrored = vol in self.ssc_vols["mirrored"] pool["netapp_mirrored"] = six.text_type(mirrored).lower() pool["netapp_unmirrored"] = six.text_type(not mirrored).lower() dedup = vol in self.ssc_vols["dedup"] pool["netapp_dedup"] = six.text_type(dedup).lower() pool["netapp_nodedup"] = six.text_type(not dedup).lower() compression = vol in self.ssc_vols["compression"] pool["netapp_compression"] = six.text_type(compression).lower() pool["netapp_nocompression"] = six.text_type(not compression).lower() thin = vol in self.ssc_vols["thin"] pool["netapp_thin_provisioned"] = six.text_type(thin).lower() pool["netapp_thick_provisioned"] = six.text_type(not thin).lower() thick = not thin and self.configuration.netapp_lun_space_reservation == "enabled" pool["thick_provisioning_support"] = thick pool["thin_provisioning_support"] = not thick utilization = self.perf_library.get_node_utilization_for_pool(pool_name) pool["utilization"] = na_utils.round_down(utilization, "0.01") pool["filter_function"] = filter_function pool["goodness_function"] = goodness_function pools.append(pool) return pools