From 81fcf8f5ea4283647d0b23dd6115ed8714625917 Mon Sep 17 00:00:00 2001 From: XinXiaohui Date: Thu, 24 Dec 2015 14:19:25 +0800 Subject: [PATCH] Wrap the method to calculate virtual free capacity There is a logic already there to calculate virtual free capacity in cinder/scheduler/weights/capacity.py. This patch is just to wrap the same logic into a method in case to avoid the inconsistency when there are some other code paths to use the the same logic seperately. The reason for the patch is that: the patch for blueprint capacity-headroom has the same code path, and some reviewers prefer to use a single method to call them in the same way. Partial-Implements: blueprint capacity-headroom Change-Id: I7554699760f2173655cb4fae434bd4933be77c9c --- cinder/scheduler/weights/capacity.py | 20 +++++++-------- cinder/tests/unit/test_utils.py | 38 ++++++++++++++++++++++++++++ cinder/utils.py | 36 ++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 11 deletions(-) diff --git a/cinder/scheduler/weights/capacity.py b/cinder/scheduler/weights/capacity.py index 6dec05bf334..31c670c9eec 100644 --- a/cinder/scheduler/weights/capacity.py +++ b/cinder/scheduler/weights/capacity.py @@ -45,6 +45,7 @@ import math from oslo_config import cfg from cinder.scheduler import weights +from cinder import utils capacity_weight_opts = [ @@ -101,7 +102,6 @@ class CapacityWeigher(weights.BaseHostWeigher): def _weigh_object(self, host_state, weight_properties): """Higher weights 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 (free_space == 'infinite' or free_space == 'unknown' or @@ -114,16 +114,14 @@ class CapacityWeigher(weights.BaseHostWeigher): # capacity anymore. free = -1 if CONF.capacity_weight_multiplier > 0 else float('inf') else: - total = float(total_space) - if host_state.thin_provisioning_support: - # Calculate virtual free capacity for thin provisioning. - free = (total * host_state.max_over_subscription_ratio - - host_state.provisioned_capacity_gb - - math.floor(total * reserved)) - else: - # Calculate how much free space is left after taking into - # account the reserved space. - free = free_space - math.floor(total * reserved) + free = utils.calculate_virtual_free_capacity( + total_space, + free_space, + host_state.provisioned_capacity_gb, + host_state.thin_provisioning_support, + host_state.max_over_subscription_ratio, + host_state.reserved_percentage) + return free diff --git a/cinder/tests/unit/test_utils.py b/cinder/tests/unit/test_utils.py index 0bddc52c9df..021ba3d9db0 100644 --- a/cinder/tests/unit/test_utils.py +++ b/cinder/tests/unit/test_utils.py @@ -1323,3 +1323,41 @@ class LogTracingTestCase(test.TestCase): self.assertEqual('OK', result) self.assertEqual(2, mock_log.debug.call_count) + + def test_utils_calculate_virtual_free_capacity_with_thick(self): + host_stat = {'total_capacity_gb': 30.01, + 'free_capacity_gb': 28.01, + 'provisioned_capacity_gb': 2.0, + 'max_over_subscription_ratio': 1.0, + 'thin_provisioning_support': False, + 'thick_provisioning_support': True, + 'reserved_percentage': 5} + + free = utils.calculate_virtual_free_capacity( + host_stat['total_capacity_gb'], + host_stat['free_capacity_gb'], + host_stat['provisioned_capacity_gb'], + host_stat['thin_provisioning_support'], + host_stat['max_over_subscription_ratio'], + host_stat['reserved_percentage']) + + self.assertEqual(27.01, free) + + def test_utils_calculate_virtual_free_capacity_with_thin(self): + host_stat = {'total_capacity_gb': 20.01, + 'free_capacity_gb': 18.01, + 'provisioned_capacity_gb': 2.0, + 'max_over_subscription_ratio': 2.0, + 'thin_provisioning_support': True, + 'thick_provisioning_support': False, + 'reserved_percentage': 5} + + free = utils.calculate_virtual_free_capacity( + host_stat['total_capacity_gb'], + host_stat['free_capacity_gb'], + host_stat['provisioned_capacity_gb'], + host_stat['thin_provisioning_support'], + host_stat['max_over_subscription_ratio'], + host_stat['reserved_percentage']) + + self.assertEqual(37.02, free) diff --git a/cinder/utils.py b/cinder/utils.py index 8a7237792fc..27a991f2c7c 100644 --- a/cinder/utils.py +++ b/cinder/utils.py @@ -24,6 +24,7 @@ import datetime import functools import inspect import logging as py_logging +import math import os import pyclbr import random @@ -995,3 +996,38 @@ def build_or_str(elements, str_format=None): if str_format: return str_format % elements return elements + + +def calculate_virtual_free_capacity(total_capacity, + free_capacity, + provisioned_capacity, + thin_provisioning_support, + max_over_subscription_ratio, + reserved_percentage): + """Calculate the virtual free capacity based on thin provisioning support. + + :param total_capacity: total_capacity_gb of a host_state or pool. + :param free_capacity: free_capacity_gb of a host_state or pool. + :param provisioned_capacity: provisioned_capacity_gb of a host_state + or pool. + :param thin_provisioning_support: thin_provisioning_support of + a host_state or a pool. + :param max_over_subscription_ratio: max_over_subscription_ratio of + a host_state or a pool + :param reserved_percentage: reserved_percentage of a host_state or + a pool. + :returns: the calculated virtual free capacity. + """ + + total = float(total_capacity) + reserved = float(reserved_percentage) / 100 + + if thin_provisioning_support: + free = (total * max_over_subscription_ratio + - provisioned_capacity + - math.floor(total * reserved)) + else: + # Calculate how much free space is left after taking into + # account the reserved space. + free = free_capacity - math.floor(total * reserved) + return free