Merge "Check 'thin_provisioning' in extra specs"

This commit is contained in:
Jenkins 2016-09-09 23:47:32 +00:00 committed by Gerrit Code Review
commit eddeff89bd
8 changed files with 388 additions and 48 deletions

View File

@ -24,6 +24,7 @@ from oslo_log import log
from manila.i18n import _LE
from manila.i18n import _LW
from manila.scheduler.filters import base_host
from manila.scheduler import utils
LOG = log.getLogger(__name__)
@ -77,14 +78,19 @@ class CapacityFilter(base_host.BaseHostFilter):
"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 thin_provisioning is True. Check if the ratio of
# provisioned capacity over total capacity would exceed
# 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 (host_state.thin_provisioning and
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)
@ -105,7 +111,8 @@ class CapacityFilter(base_host.BaseHostFilter):
adjusted_free_virtual = (
free * host_state.max_over_subscription_ratio)
return adjusted_free_virtual >= share_size
elif host_state.thin_provisioning:
elif (use_thin_logic and thin_provisioning and
host_state.max_over_subscription_ratio < 1):
LOG.error(_LE("Invalid max_over_subscription_ratio: %(ratio)s. "
"Valid value should be >= 1."),
{"ratio": host_state.max_over_subscription_ratio})

View File

@ -1,4 +1,6 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
# Copyright (c) 2016 EMC Corporation
#
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -13,6 +15,10 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_utils import strutils
from manila.scheduler.filters import extra_specs_ops
def generate_stats(host_state, properties):
"""Generates statistics from host and share data."""
@ -61,3 +67,47 @@ def generate_stats(host_state, properties):
}
return stats
def use_thin_logic(share_type):
# NOTE(xyang): To preserve the existing behavior, we use thin logic
# to evaluate in two cases:
# 1) 'thin_provisioning' is not set in extra specs (This is for
# backward compatibility. If not set, the scheduler behaves
# the same as before this bug fix).
# 2) 'thin_provisioning' is set in extra specs and it is
# '<is> True' or 'True'.
# Otherwise we use the thick logic to evaluate.
use_thin_logic = True
thin_spec = None
try:
thin_spec = share_type.get('extra_specs', {}).get(
'thin_provisioning')
if thin_spec is None:
thin_spec = share_type.get('extra_specs', {}).get(
'capabilities:thin_provisioning')
# NOTE(xyang) 'use_thin_logic' and 'thin_provisioning' are NOT
# the same thing. The first purpose of "use_thin_logic" is to
# preserve the existing scheduler behavior if 'thin_provisioning'
# is NOT in extra_specs (if thin_spec is None, use_thin_logic
# should be True). The second purpose of 'use_thin_logic'
# is to honor 'thin_provisioning' if it is in extra specs (if
# thin_spec is set to True, use_thin_logic should be True; if
# thin_spec is set to False, use_thin_logic should be False).
use_thin_logic = strutils.bool_from_string(
thin_spec, strict=True) if thin_spec is not None else True
except ValueError:
# Check if the value of thin_spec is '<is> True'.
if thin_spec is not None and not extra_specs_ops.match(
True, thin_spec):
use_thin_logic = False
return use_thin_logic
def thin_provisioning(host_state_thin_provisioning):
# NOTE(xyang): host_state_thin_provisioning is reported by driver.
# It can be either bool (True or False) or
# list ([True, False], [True], [False]).
thin_capability = [host_state_thin_provisioning] if not isinstance(
host_state_thin_provisioning, list) else host_state_thin_provisioning
return True in thin_capability

View File

@ -31,7 +31,7 @@ import math
from oslo_config import cfg
from manila.scheduler import utils
from manila.scheduler.weighers import base_host
capacity_weight_opts = [
@ -63,7 +63,13 @@ class CapacityWeigher(base_host.BaseHostWeigher):
free = float('inf')
else:
total = float(total_space)
if host_state.thin_provisioning:
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(

View File

@ -212,7 +212,7 @@ class FakeHostManager(host_manager.HostManager):
'allocated_capacity_gb': 256,
'provisioned_capacity_gb': 256,
'max_over_subscription_ratio': 2.0,
'thin_provisioning': False,
'thin_provisioning': [False],
'consistency_group_support': 'host',
'reserved_percentage': 0,
'snapshot_support': True,
@ -223,7 +223,7 @@ class FakeHostManager(host_manager.HostManager):
'allocated_capacity_gb': 1848,
'provisioned_capacity_gb': 1848,
'max_over_subscription_ratio': 1.0,
'thin_provisioning': True,
'thin_provisioning': [True],
'reserved_percentage': 5,
'timestamp': None,
'snapshot_support': True,
@ -235,7 +235,7 @@ class FakeHostManager(host_manager.HostManager):
'allocated_capacity_gb': 1548,
'provisioned_capacity_gb': 1548,
'max_over_subscription_ratio': 1.5,
'thin_provisioning': True,
'thin_provisioning': [True, False],
'reserved_percentage': 5,
'timestamp': None,
'snapshot_support': True,

View File

@ -121,31 +121,76 @@ class HostFiltersTestCase(test.TestCase):
@ddt.data(
{'size': 100, 'cap_thin': '<is> True',
'total': 500, 'free': 200, 'provisioned': 500,
'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True},
'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True,
'cap_thin_key': 'capabilities:thin_provisioning'},
{'size': 3000, 'cap_thin': '<is> True',
'total': 500, 'free': 200, 'provisioned': 7000,
'max_ratio': 20, 'reserved': 5, 'thin_prov': True},
'max_ratio': 20, 'reserved': 5, 'thin_prov': True,
'cap_thin_key': 'thin_provisioning'},
{'size': 100, 'cap_thin': '<is> False',
'total': 500, 'free': 200, 'provisioned': 300,
'max_ratio': 1.0, 'reserved': 5, 'thin_prov': False},
'max_ratio': 1.0, 'reserved': 5, 'thin_prov': False,
'cap_thin_key': 'capabilities:thin_provisioning'},
{'size': 100, 'cap_thin': '<is> True',
'total': 500, 'free': 200, 'provisioned': 400,
'max_ratio': 1.0, 'reserved': 5, 'thin_prov': True},
'max_ratio': 1.0, 'reserved': 5, 'thin_prov': True,
'cap_thin_key': 'thin_provisioning'},
{'size': 100, 'cap_thin': '<is> True',
'total': 500, 'free': 125, 'provisioned': 400,
'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True},
'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True,
'cap_thin_key': 'capabilities:thin_provisioning'},
{'size': 100, 'cap_thin': '<is> True',
'total': 500, 'free': 80, 'provisioned': 600,
'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True},
'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True,
'cap_thin_key': 'thin_provisioning'},
{'size': 100, 'cap_thin': '<is> True',
'total': 500, 'free': 100, 'provisioned': 400,
'max_ratio': 2.0, 'reserved': 0, 'thin_prov': True})
'max_ratio': 2.0, 'reserved': 0, 'thin_prov': True,
'cap_thin_key': 'capabilities:thin_provisioning'},
{'size': 100, 'cap_thin': '<is> True',
'total': 500, 'free': 200, 'provisioned': 500,
'max_ratio': 2.0, 'reserved': 5, 'thin_prov': [True, False],
'cap_thin_key': 'thin_provisioning'},
{'size': 3000, 'cap_thin': '<is> True',
'total': 500, 'free': 200, 'provisioned': 7000,
'max_ratio': 20, 'reserved': 5, 'thin_prov': [True],
'cap_thin_key': 'capabilities:thin_provisioning'},
{'size': 100, 'cap_thin': '<is> False',
'total': 500, 'free': 200, 'provisioned': 300,
'max_ratio': 1.0, 'reserved': 5, 'thin_prov': [False],
'cap_thin_key': 'thin_provisioning'},
{'size': 100, 'cap_thin': 'True',
'total': 500, 'free': 200, 'provisioned': 400,
'max_ratio': 1.0, 'reserved': 5, 'thin_prov': [False, True],
'cap_thin_key': 'capabilities:thin_provisioning'},
{'size': 100, 'cap_thin': 'False',
'total': 500, 'free': 200, 'provisioned': 300,
'max_ratio': 1.0, 'reserved': 5, 'thin_prov': False,
'cap_thin_key': 'thin_provisioning'},
{'size': 100, 'cap_thin': 'true',
'total': 500, 'free': 125, 'provisioned': 400,
'max_ratio': 2.0, 'reserved': 5, 'thin_prov': [True, ],
'cap_thin_key': 'capabilities:thin_provisioning'},
{'size': 100, 'cap_thin': 'false',
'total': 500, 'free': 200, 'provisioned': 300,
'max_ratio': 1.0, 'reserved': 5, 'thin_prov': [False, ],
'cap_thin_key': 'thin_provisioning'},
{'size': 100, 'cap_thin': None,
'total': 500, 'free': 80, 'provisioned': 600,
'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True,
'cap_thin_key': None},)
@ddt.unpack
def test_filter_thin_passes(self, size, cap_thin, total, free, provisioned,
max_ratio, reserved, thin_prov):
max_ratio, reserved, thin_prov, cap_thin_key):
self._stub_service_is_up(True)
filter_properties = {'size': size,
'capabilities:thin_provisioning': cap_thin}
filter_properties = {
'size': size,
'share_type': {
'extra_specs': {
cap_thin_key: cap_thin,
}
}
}
service = {'disabled': False}
host = fakes.FakeHostState('host1',
{'total_capacity_gb': total,
@ -161,34 +206,80 @@ class HostFiltersTestCase(test.TestCase):
@ddt.data(
{'size': 200, 'cap_thin': '<is> True',
'total': 500, 'free': 100, 'provisioned': 400,
'max_ratio': 0.8, 'reserved': 0, 'thin_prov': True},
'max_ratio': 0.8, 'reserved': 0, 'thin_prov': True,
'cap_thin_key': 'capabilities:thin_provisioning'},
{'size': 100, 'cap_thin': '<is> True',
'total': 500, 'free': 200, 'provisioned': 700,
'max_ratio': 1.5, 'reserved': 5, 'thin_prov': True},
'max_ratio': 1.5, 'reserved': 5, 'thin_prov': True,
'cap_thin_key': 'thin_provisioning'},
{'size': 2000, 'cap_thin': '<is> True',
'total': 500, 'free': 30, 'provisioned': 9000,
'max_ratio': 20.0, 'reserved': 0, 'thin_prov': True},
'max_ratio': 20.0, 'reserved': 0, 'thin_prov': True,
'cap_thin_key': 'capabilities:thin_provisioning'},
{'size': 100, 'cap_thin': '<is> True',
'total': 500, 'free': 100, 'provisioned': 1000,
'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True},
'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True,
'cap_thin_key': 'thin_provisioning'},
{'size': 100, 'cap_thin': '<is> False',
'total': 500, 'free': 100, 'provisioned': 400,
'max_ratio': 1.0, 'reserved': 5, 'thin_prov': False},
'max_ratio': 1.0, 'reserved': 5, 'thin_prov': False,
'cap_thin_key': 'capabilities:thin_provisioning'},
{'size': 100, 'cap_thin': '<is> True',
'total': 500, 'free': 0, 'provisioned': 800,
'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True},
'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True,
'cap_thin_key': 'thin_provisioning'},
{'size': 100, 'cap_thin': '<is> True',
'total': 500, 'free': 99, 'provisioned': 1000,
'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True},
'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True,
'cap_thin_key': 'capabilities:thin_provisioning'},
{'size': 400, 'cap_thin': '<is> True',
'total': 500, 'free': 200, 'provisioned': 600,
'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True})
'max_ratio': 2.0, 'reserved': 5, 'thin_prov': True,
'cap_thin_key': 'thin_provisioning'},
{'size': 200, 'cap_thin': '<is> True',
'total': 500, 'free': 100, 'provisioned': 400,
'max_ratio': 0.8, 'reserved': 0, 'thin_prov': [False, True],
'cap_thin_key': 'capabilities:thin_provisioning'},
{'size': 2000, 'cap_thin': '<is> True',
'total': 500, 'free': 30, 'provisioned': 9000,
'max_ratio': 20.0, 'reserved': 0, 'thin_prov': [True],
'cap_thin_key': 'thin_provisioning'},
{'size': 100, 'cap_thin': '<is> False',
'total': 500, 'free': 100, 'provisioned': 400,
'max_ratio': 1.0, 'reserved': 5, 'thin_prov': [False],
'cap_thin_key': 'thin_provisioning'},
{'size': 100, 'cap_thin': 'False',
'total': 500, 'free': 100, 'provisioned': 400,
'max_ratio': 1.0, 'reserved': 5, 'thin_prov': False,
'cap_thin_key': 'capabilities:thin_provisioning'},
{'size': 100, 'cap_thin': 'True',
'total': 500, 'free': 0, 'provisioned': 800,
'max_ratio': 2.0, 'reserved': 5, 'thin_prov': [False, True],
'cap_thin_key': 'thin_provisioning'},
{'size': 100, 'cap_thin': 'true',
'total': 500, 'free': 99, 'provisioned': 1000,
'max_ratio': 2.0, 'reserved': 5, 'thin_prov': [True, ],
'cap_thin_key': 'capabilities:thin_provisioning'},
{'size': 100, 'cap_thin': 'false',
'total': 500, 'free': 100, 'provisioned': 400,
'max_ratio': 1.0, 'reserved': 5, 'thin_prov': [False, ],
'cap_thin_key': 'thin_provisioning'},
{'size': 2000, 'cap_thin': None,
'total': 500, 'free': 30, 'provisioned': 9000,
'max_ratio': 20.0, 'reserved': 0, 'thin_prov': [True],
'cap_thin_key': None},)
@ddt.unpack
def test_filter_thin_fails(self, size, cap_thin, total, free, provisioned,
max_ratio, reserved, thin_prov):
max_ratio, reserved, thin_prov, cap_thin_key):
self._stub_service_is_up(True)
filter_properties = {'size': size,
'capabilities:thin_provisioning': cap_thin}
filter_properties = {
'size': size,
'share_type': {
'extra_specs': {
cap_thin_key: cap_thin,
}
}
}
service = {'disabled': False}
host = fakes.FakeHostState('host1',
{'total_capacity_gb': total,

View File

@ -0,0 +1,64 @@
# Copyright 2016 EMC Corporation OpenStack Foundation.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Tests For utils.
"""
import ddt
from manila.scheduler import utils
from manila import test
@ddt.ddt
class UtilsTestCase(test.TestCase):
"""Test case for utils."""
def setUp(self):
super(UtilsTestCase, self).setUp()
@ddt.data(
({'extra_specs': {'thin_provisioning': True}}, True),
({'extra_specs': {'thin_provisioning': False}}, False),
({'extra_specs': {'foo': 'bar'}}, True),
({'foo': 'bar'}, True),
({'extra_specs': {'thin_provisioning': '<is> True'}},
True),
({'extra_specs': {'thin_provisioning': '<is> False'}},
False),
({'extra_specs': {'thin_provisioning': '<not> True'}},
False),
({'extra_specs': {}}, True),
({}, True),
)
@ddt.unpack
def test_use_thin_logic(self, properties, use_thin):
use_thin_logic = utils.use_thin_logic(properties)
self.assertEqual(use_thin, use_thin_logic)
@ddt.data(
(True, True),
(False, False),
(None, False),
([True, False], True),
([True], True),
([False], False),
('wrong', False),
)
@ddt.unpack
def test_thin_provisioning(self, thin_capabilities, thin):
thin_provisioning = utils.thin_provisioning(thin_capabilities)
self.assertEqual(thin, thin_provisioning)

View File

@ -16,6 +16,7 @@
Tests For Capacity Weigher.
"""
import ddt
import mock
from oslo_config import cfg
@ -29,6 +30,7 @@ from manila.tests.scheduler import fakes
CONF = cfg.CONF
@ddt.ddt
class CapacityWeigherTestCase(test.TestCase):
def setUp(self):
super(CapacityWeigherTestCase, self).setUp()
@ -61,9 +63,37 @@ class CapacityWeigherTestCase(test.TestCase):
# - total * reserved)
# Otherwise, use the following formula:
# free = math.floor(free_space - total * reserved)
def test_default_of_spreading_first(self):
@ddt.data(
{'cap_thin': '<is> True',
'cap_thin_key': 'capabilities:thin_provisioning',
'winner': 'host2'},
{'cap_thin': '<is> False',
'cap_thin_key': 'thin_provisioning',
'winner': 'host1'},
{'cap_thin': 'True',
'cap_thin_key': 'capabilities:thin_provisioning',
'winner': 'host2'},
{'cap_thin': 'False',
'cap_thin_key': 'thin_provisioning',
'winner': 'host1'},
{'cap_thin': 'true',
'cap_thin_key': 'capabilities:thin_provisioning',
'winner': 'host2'},
{'cap_thin': 'false',
'cap_thin_key': 'thin_provisioning',
'winner': 'host1'},
{'cap_thin': None,
'cap_thin_key': None,
'winner': 'host2'},
)
@ddt.unpack
def test_default_of_spreading_first(self, cap_thin, cap_thin_key,
winner):
hostinfo_list = self._get_all_hosts()
# Results for the 1st test
# {'capabilities:thin_provisioning': '<is> True'}:
# host1: thin_provisioning = False
# free_capacity_gb = 1024
# free = math.floor(1024 - 1024 * 0.1) = 921.0
@ -73,16 +103,16 @@ class CapacityWeigherTestCase(test.TestCase):
# free_capacity_gb = 300
# free = math.floor(2048 * 2.0 - 1748 - 2048 * 0.1)=2143.0
# weight = 1.0
# host3: thin_provisioning = False
# host3: thin_provisioning = [False]
# free_capacity_gb = 512
# free = math.floor(256 - 512 * 0)=256.0
# weight = 0.08
# host4: thin_provisioning = True
# host4: thin_provisioning = [True]
# max_over_subscription_ratio = 1.0
# free_capacity_gb = 200
# free = math.floor(2048 * 1.0 - 1848 - 2048 * 0.05) = 97.0
# weight = 0.0
# host5: thin_provisioning = True
# host5: thin_provisioning = [True, False]
# max_over_subscription_ratio = 1.5
# free_capacity_gb = 500
# free = math.floor(2048 * 1.5 - 1548 - 2048 * 0.05) = 1421.0
@ -92,10 +122,20 @@ class CapacityWeigherTestCase(test.TestCase):
# weight = 0.0
# so, host2 should win:
weighed_host = self._get_weighed_host(hostinfo_list)
weight_properties = {
'size': 1,
'share_type': {
'extra_specs': {
cap_thin_key: cap_thin,
}
}
}
weighed_host = self._get_weighed_host(
hostinfo_list,
weight_properties=weight_properties)
self.assertEqual(1.0, weighed_host.weight)
self.assertEqual(
'host2', utils.extract_host(weighed_host.obj.host))
winner, utils.extract_host(weighed_host.obj.host))
def test_unknown_is_last(self):
hostinfo_list = self._get_all_hosts()
@ -105,10 +145,38 @@ class CapacityWeigherTestCase(test.TestCase):
'host6', utils.extract_host(last_host.obj.host))
self.assertEqual(0.0, last_host.weight)
def test_capacity_weight_multiplier_negative_1(self):
@ddt.data(
{'cap_thin': '<is> True',
'cap_thin_key': 'capabilities:thin_provisioning',
'winner': 'host4'},
{'cap_thin': '<is> False',
'cap_thin_key': 'thin_provisioning',
'winner': 'host2'},
{'cap_thin': 'True',
'cap_thin_key': 'capabilities:thin_provisioning',
'winner': 'host4'},
{'cap_thin': 'False',
'cap_thin_key': 'thin_provisioning',
'winner': 'host2'},
{'cap_thin': 'true',
'cap_thin_key': 'capabilities:thin_provisioning',
'winner': 'host4'},
{'cap_thin': 'false',
'cap_thin_key': 'thin_provisioning',
'winner': 'host2'},
{'cap_thin': None,
'cap_thin_key': None,
'winner': 'host4'},
)
@ddt.unpack
def test_capacity_weight_multiplier_negative_1(self, cap_thin,
cap_thin_key,
winner):
self.flags(capacity_weight_multiplier=-1.0)
hostinfo_list = self._get_all_hosts()
# Results for the 1st test
# {'capabilities:thin_provisioning': '<is> True'}:
# host1: thin_provisioning = False
# free_capacity_gb = 1024
# free = math.floor(1024 - 1024 * 0.1) = 921.0
@ -120,18 +188,18 @@ class CapacityWeigherTestCase(test.TestCase):
# free = math.floor(2048 * 2.0-1748-2048 * 0.1) = 2143.0
# free * (-1) = -2143.0
# weight = -1.0
# host3: thin_provisioning = False
# host3: thin_provisioning = [False]
# free_capacity_gb = 512
# free = math.floor(256 - 512 * 0) = 256.0
# free * (-1) = -256.0
# weight = -0.08
# host4: thin_provisioning = True
# host4: thin_provisioning = [True]
# max_over_subscription_ratio = 1.0
# free_capacity_gb = 200
# free = math.floor(2048 * 1.0 - 1848 - 2048 * 0.05) = 97.0
# free * (-1) = -97.0
# weight = 0.0
# host5: thin_provisioning = True
# host5: thin_provisioning = [True, False]
# max_over_subscription_ratio = 1.5
# free_capacity_gb = 500
# free = math.floor(2048 * 1.5 - 1548 - 2048 * 0.05) = 1421.0
@ -143,15 +211,52 @@ class CapacityWeigherTestCase(test.TestCase):
# weight = 0.0
# so, host4 should win:
weighed_host = self._get_weighed_host(hostinfo_list)
weight_properties = {
'size': 1,
'share_type': {
'extra_specs': {
cap_thin_key: cap_thin,
}
}
}
weighed_host = self._get_weighed_host(
hostinfo_list,
weight_properties=weight_properties)
self.assertEqual(0.0, weighed_host.weight)
self.assertEqual(
'host4', utils.extract_host(weighed_host.obj.host))
winner, utils.extract_host(weighed_host.obj.host))
def test_capacity_weight_multiplier_2(self):
@ddt.data(
{'cap_thin': '<is> True',
'cap_thin_key': 'capabilities:thin_provisioning',
'winner': 'host2'},
{'cap_thin': '<is> False',
'cap_thin_key': 'thin_provisioning',
'winner': 'host1'},
{'cap_thin': 'True',
'cap_thin_key': 'capabilities:thin_provisioning',
'winner': 'host2'},
{'cap_thin': 'False',
'cap_thin_key': 'thin_provisioning',
'winner': 'host1'},
{'cap_thin': 'true',
'cap_thin_key': 'capabilities:thin_provisioning',
'winner': 'host2'},
{'cap_thin': 'false',
'cap_thin_key': 'thin_provisioning',
'winner': 'host1'},
{'cap_thin': None,
'cap_thin_key': None,
'winner': 'host2'},
)
@ddt.unpack
def test_capacity_weight_multiplier_2(self, cap_thin, cap_thin_key,
winner):
self.flags(capacity_weight_multiplier=2.0)
hostinfo_list = self._get_all_hosts()
# Results for the 1st test
# {'capabilities:thin_provisioning': '<is> True'}:
# host1: thin_provisioning = False
# free_capacity_gb = 1024
# free = math.floor(1024-1024*0.1) = 921.0
@ -163,18 +268,18 @@ class CapacityWeigherTestCase(test.TestCase):
# free = math.floor(2048 * 2.0 - 1748 - 2048 * 0.1) = 2143.0
# free * 2 = 4286.0
# weight = 2.0
# host3: thin_provisioning = False
# host3: thin_provisioning = [False]
# free_capacity_gb = 512
# free = math.floor(256 - 512 * 0) = 256.0
# free * 2 = 512.0
# weight = 0.16
# host4: thin_provisioning = True
# host4: thin_provisioning = [True]
# max_over_subscription_ratio = 1.0
# free_capacity_gb = 200
# free = math.floor(2048 * 1.0 - 1848 - 2048 * 0.05) = 97.0
# free * 2 = 194.0
# weight = 0.0
# host5: thin_provisioning = True
# host5: thin_provisioning = [True, False]
# max_over_subscription_ratio = 1.5
# free_capacity_gb = 500
# free = math.floor(2048 * 1.5 - 1548 - 2048 * 0.05) = 1421.0
@ -185,7 +290,17 @@ class CapacityWeigherTestCase(test.TestCase):
# weight = 0.0
# so, host2 should win:
weighed_host = self._get_weighed_host(hostinfo_list)
weight_properties = {
'size': 1,
'share_type': {
'extra_specs': {
cap_thin_key: cap_thin,
}
}
}
weighed_host = self._get_weighed_host(
hostinfo_list,
weight_properties=weight_properties)
self.assertEqual(2.0, weighed_host.weight)
self.assertEqual(
'host2', utils.extract_host(weighed_host.obj.host))
winner, utils.extract_host(weighed_host.obj.host))

View File

@ -0,0 +1,7 @@
---
fixes:
- Capacity filter and weigher scheduler logic was modified to
account for back ends that can support thin and thick provisioning
for shares. Over subscription calculation is triggered with the
presence of the ``thin_provisioning`` extra-spec in the share type
of the share being created.