Merge "Overprovisioning Improvements"
This commit is contained in:
commit
b9224e3a00
@ -335,6 +335,7 @@ class PoolState(BackendState):
|
|||||||
|
|
||||||
def update_from_volume_capability(self, capability, service=None):
|
def update_from_volume_capability(self, capability, service=None):
|
||||||
"""Update information about a pool from its volume_node info."""
|
"""Update information about a pool from its volume_node info."""
|
||||||
|
LOG.debug("Updating capabilities for %s: %s", self.host, capability)
|
||||||
self.update_capabilities(capability, service)
|
self.update_capabilities(capability, service)
|
||||||
if capability:
|
if capability:
|
||||||
if self.updated and self.updated > capability['timestamp']:
|
if self.updated and self.updated > capability['timestamp']:
|
||||||
@ -355,13 +356,15 @@ class PoolState(BackendState):
|
|||||||
# provisioned_capacity_gb if it is not set.
|
# provisioned_capacity_gb if it is not set.
|
||||||
self.provisioned_capacity_gb = capability.get(
|
self.provisioned_capacity_gb = capability.get(
|
||||||
'provisioned_capacity_gb', self.allocated_capacity_gb)
|
'provisioned_capacity_gb', self.allocated_capacity_gb)
|
||||||
self.max_over_subscription_ratio = capability.get(
|
|
||||||
'max_over_subscription_ratio',
|
|
||||||
CONF.max_over_subscription_ratio)
|
|
||||||
self.thin_provisioning_support = capability.get(
|
self.thin_provisioning_support = capability.get(
|
||||||
'thin_provisioning_support', False)
|
'thin_provisioning_support', False)
|
||||||
self.thick_provisioning_support = capability.get(
|
self.thick_provisioning_support = capability.get(
|
||||||
'thick_provisioning_support', False)
|
'thick_provisioning_support', False)
|
||||||
|
|
||||||
|
self.max_over_subscription_ratio = (
|
||||||
|
utils.calculate_max_over_subscription_ratio(
|
||||||
|
capability, CONF.max_over_subscription_ratio))
|
||||||
|
|
||||||
self.multiattach = capability.get('multiattach', False)
|
self.multiattach = capability.get('multiattach', False)
|
||||||
|
|
||||||
def update_pools(self, capability):
|
def update_pools(self, capability):
|
||||||
@ -756,7 +759,8 @@ class HostManager(object):
|
|||||||
allocated = pool["allocated_capacity_gb"]
|
allocated = pool["allocated_capacity_gb"]
|
||||||
provisioned = pool["provisioned_capacity_gb"]
|
provisioned = pool["provisioned_capacity_gb"]
|
||||||
reserved = pool["reserved_percentage"]
|
reserved = pool["reserved_percentage"]
|
||||||
ratio = pool["max_over_subscription_ratio"]
|
ratio = utils.calculate_max_over_subscription_ratio(
|
||||||
|
pool, CONF.max_over_subscription_ratio)
|
||||||
support = pool["thin_provisioning_support"]
|
support = pool["thin_provisioning_support"]
|
||||||
|
|
||||||
virtual_free = utils.calculate_virtual_free_capacity(
|
virtual_free = utils.calculate_virtual_free_capacity(
|
||||||
|
@ -32,7 +32,7 @@ SERVICE_STATES = {
|
|||||||
'free_capacity_gb': 1024,
|
'free_capacity_gb': 1024,
|
||||||
'allocated_capacity_gb': 0,
|
'allocated_capacity_gb': 0,
|
||||||
'provisioned_capacity_gb': 0,
|
'provisioned_capacity_gb': 0,
|
||||||
'max_over_subscription_ratio': 1.0,
|
'max_over_subscription_ratio': '1.0',
|
||||||
'thin_provisioning_support': False,
|
'thin_provisioning_support': False,
|
||||||
'thick_provisioning_support': True,
|
'thick_provisioning_support': True,
|
||||||
'reserved_percentage': 10,
|
'reserved_percentage': 10,
|
||||||
@ -44,7 +44,7 @@ SERVICE_STATES = {
|
|||||||
'free_capacity_gb': 300,
|
'free_capacity_gb': 300,
|
||||||
'allocated_capacity_gb': 1748,
|
'allocated_capacity_gb': 1748,
|
||||||
'provisioned_capacity_gb': 1748,
|
'provisioned_capacity_gb': 1748,
|
||||||
'max_over_subscription_ratio': 1.5,
|
'max_over_subscription_ratio': '1.5',
|
||||||
'thin_provisioning_support': True,
|
'thin_provisioning_support': True,
|
||||||
'thick_provisioning_support': False,
|
'thick_provisioning_support': False,
|
||||||
'reserved_percentage': 10,
|
'reserved_percentage': 10,
|
||||||
@ -55,7 +55,7 @@ SERVICE_STATES = {
|
|||||||
'free_capacity_gb': 256,
|
'free_capacity_gb': 256,
|
||||||
'allocated_capacity_gb': 256,
|
'allocated_capacity_gb': 256,
|
||||||
'provisioned_capacity_gb': 256,
|
'provisioned_capacity_gb': 256,
|
||||||
'max_over_subscription_ratio': 2.0,
|
'max_over_subscription_ratio': '2.0',
|
||||||
'thin_provisioning_support': False,
|
'thin_provisioning_support': False,
|
||||||
'thick_provisioning_support': True,
|
'thick_provisioning_support': True,
|
||||||
'reserved_percentage': 0,
|
'reserved_percentage': 0,
|
||||||
@ -66,7 +66,7 @@ SERVICE_STATES = {
|
|||||||
'free_capacity_gb': 200,
|
'free_capacity_gb': 200,
|
||||||
'allocated_capacity_gb': 1848,
|
'allocated_capacity_gb': 1848,
|
||||||
'provisioned_capacity_gb': 2047,
|
'provisioned_capacity_gb': 2047,
|
||||||
'max_over_subscription_ratio': 1.0,
|
'max_over_subscription_ratio': '1.0',
|
||||||
'thin_provisioning_support': True,
|
'thin_provisioning_support': True,
|
||||||
'thick_provisioning_support': False,
|
'thick_provisioning_support': False,
|
||||||
'reserved_percentage': 5,
|
'reserved_percentage': 5,
|
||||||
@ -78,7 +78,7 @@ SERVICE_STATES = {
|
|||||||
'free_capacity_gb': 'unknown',
|
'free_capacity_gb': 'unknown',
|
||||||
'allocated_capacity_gb': 1548,
|
'allocated_capacity_gb': 1548,
|
||||||
'provisioned_capacity_gb': 1548,
|
'provisioned_capacity_gb': 1548,
|
||||||
'max_over_subscription_ratio': 1.0,
|
'max_over_subscription_ratio': '1.0',
|
||||||
'thin_provisioning_support': True,
|
'thin_provisioning_support': True,
|
||||||
'thick_provisioning_support': False,
|
'thick_provisioning_support': False,
|
||||||
'reserved_percentage': 5,
|
'reserved_percentage': 5,
|
||||||
@ -98,7 +98,7 @@ SERVICE_STATES_WITH_POOLS = {
|
|||||||
'free_capacity_gb': 1024,
|
'free_capacity_gb': 1024,
|
||||||
'allocated_capacity_gb': 0,
|
'allocated_capacity_gb': 0,
|
||||||
'provisioned_capacity_gb': 0,
|
'provisioned_capacity_gb': 0,
|
||||||
'max_over_subscription_ratio': 1.0,
|
'max_over_subscription_ratio': '1.0',
|
||||||
'thin_provisioning_support': False,
|
'thin_provisioning_support': False,
|
||||||
'thick_provisioning_support': True,
|
'thick_provisioning_support': True,
|
||||||
'reserved_percentage': 15,
|
'reserved_percentage': 15,
|
||||||
@ -109,7 +109,7 @@ SERVICE_STATES_WITH_POOLS = {
|
|||||||
'free_capacity_gb': 1008,
|
'free_capacity_gb': 1008,
|
||||||
'allocated_capacity_gb': 0,
|
'allocated_capacity_gb': 0,
|
||||||
'provisioned_capacity_gb': 0,
|
'provisioned_capacity_gb': 0,
|
||||||
'max_over_subscription_ratio': 1.0,
|
'max_over_subscription_ratio': '1.0',
|
||||||
'thin_provisioning_support': True,
|
'thin_provisioning_support': True,
|
||||||
'thick_provisioning_support': False,
|
'thick_provisioning_support': False,
|
||||||
'reserved_percentage': 15,
|
'reserved_percentage': 15,
|
||||||
@ -131,7 +131,7 @@ SERVICE_STATES_WITH_POOLS = {
|
|||||||
'free_capacity_gb': 300,
|
'free_capacity_gb': 300,
|
||||||
'allocated_capacity_gb': 1748,
|
'allocated_capacity_gb': 1748,
|
||||||
'provisioned_capacity_gb': 1748,
|
'provisioned_capacity_gb': 1748,
|
||||||
'max_over_subscription_ratio': 1.5,
|
'max_over_subscription_ratio': '1.5',
|
||||||
'thin_provisioning_support': True,
|
'thin_provisioning_support': True,
|
||||||
'thick_provisioning_support': False,
|
'thick_provisioning_support': False,
|
||||||
'reserved_percentage': 10,
|
'reserved_percentage': 10,
|
||||||
@ -142,7 +142,7 @@ SERVICE_STATES_WITH_POOLS = {
|
|||||||
'free_capacity_gb': 256,
|
'free_capacity_gb': 256,
|
||||||
'allocated_capacity_gb': 256,
|
'allocated_capacity_gb': 256,
|
||||||
'provisioned_capacity_gb': 256,
|
'provisioned_capacity_gb': 256,
|
||||||
'max_over_subscription_ratio': 2.0,
|
'max_over_subscription_ratio': '2.0',
|
||||||
'thin_provisioning_support': True,
|
'thin_provisioning_support': True,
|
||||||
'thick_provisioning_support': False,
|
'thick_provisioning_support': False,
|
||||||
'reserved_percentage': 10,
|
'reserved_percentage': 10,
|
||||||
@ -160,7 +160,7 @@ SERVICE_STATES_WITH_POOLS = {
|
|||||||
'free_capacity_gb': 256,
|
'free_capacity_gb': 256,
|
||||||
'allocated_capacity_gb': 256,
|
'allocated_capacity_gb': 256,
|
||||||
'provisioned_capacity_gb': 256,
|
'provisioned_capacity_gb': 256,
|
||||||
'max_over_subscription_ratio': 2.0,
|
'max_over_subscription_ratio': '2.0',
|
||||||
'thin_provisioning_support': False,
|
'thin_provisioning_support': False,
|
||||||
'thick_provisioning_support': True,
|
'thick_provisioning_support': True,
|
||||||
'reserved_percentage': 0,
|
'reserved_percentage': 0,
|
||||||
@ -180,7 +180,7 @@ SERVICE_STATES_WITH_POOLS = {
|
|||||||
'free_capacity_gb': 'unknown',
|
'free_capacity_gb': 'unknown',
|
||||||
'allocated_capacity_gb': 170,
|
'allocated_capacity_gb': 170,
|
||||||
'provisioned_capacity_gb': 170,
|
'provisioned_capacity_gb': 170,
|
||||||
'max_over_subscription_ratio': 1.0,
|
'max_over_subscription_ratio': '1.0',
|
||||||
'thin_provisioning_support': False,
|
'thin_provisioning_support': False,
|
||||||
'thick_provisioning_support': True,
|
'thick_provisioning_support': True,
|
||||||
'QoS_support': True,
|
'QoS_support': True,
|
||||||
@ -192,7 +192,7 @@ SERVICE_STATES_WITH_POOLS = {
|
|||||||
'free_capacity_gb': 'unknown',
|
'free_capacity_gb': 'unknown',
|
||||||
'allocated_capacity_gb': 1548,
|
'allocated_capacity_gb': 1548,
|
||||||
'provisioned_capacity_gb': 1548,
|
'provisioned_capacity_gb': 1548,
|
||||||
'max_over_subscription_ratio': 1.0,
|
'max_over_subscription_ratio': '1.0',
|
||||||
'thin_provisioning_support': True,
|
'thin_provisioning_support': True,
|
||||||
'thick_provisioning_support': False,
|
'thick_provisioning_support': False,
|
||||||
'QoS_support': True,
|
'QoS_support': True,
|
||||||
|
@ -155,7 +155,8 @@ class CapacityWeigherTestCase(test.TestCase):
|
|||||||
}
|
}
|
||||||
weighed_host = self._get_weighed_hosts(
|
weighed_host = self._get_weighed_hosts(
|
||||||
backend_info_list,
|
backend_info_list,
|
||||||
weight_properties=weight_properties)[0]
|
weight_properties=weight_properties)
|
||||||
|
weighed_host = weighed_host[0]
|
||||||
self.assertEqual(0.0, weighed_host.weight)
|
self.assertEqual(0.0, weighed_host.weight)
|
||||||
self.assertEqual(winner, utils.extract_host(weighed_host.obj.host))
|
self.assertEqual(winner, utils.extract_host(weighed_host.obj.host))
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
capab1 = {'pools': [{
|
capab1 = {'pools': [{
|
||||||
'pool_name': 'pool1', 'thick_provisioning_support': True,
|
'pool_name': 'pool1', 'thick_provisioning_support': True,
|
||||||
'thin_provisioning_support': False, 'total_capacity_gb': 10,
|
'thin_provisioning_support': False, 'total_capacity_gb': 10,
|
||||||
'free_capacity_gb': 10, 'max_over_subscription_ratio': 1,
|
'free_capacity_gb': 10, 'max_over_subscription_ratio': '1',
|
||||||
'provisioned_capacity_gb': 0, 'allocated_capacity_gb': 0,
|
'provisioned_capacity_gb': 0, 'allocated_capacity_gb': 0,
|
||||||
'reserved_percentage': 0}]}
|
'reserved_percentage': 0}]}
|
||||||
|
|
||||||
@ -210,7 +210,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
capab1 = {'pools': [{
|
capab1 = {'pools': [{
|
||||||
'pool_name': 'pool1', 'thick_provisioning_support': True,
|
'pool_name': 'pool1', 'thick_provisioning_support': True,
|
||||||
'thin_provisioning_support': False, 'total_capacity_gb': 10,
|
'thin_provisioning_support': False, 'total_capacity_gb': 10,
|
||||||
'free_capacity_gb': 10, 'max_over_subscription_ratio': 1,
|
'free_capacity_gb': 10, 'max_over_subscription_ratio': '1',
|
||||||
'provisioned_capacity_gb': 0, 'allocated_capacity_gb': 0,
|
'provisioned_capacity_gb': 0, 'allocated_capacity_gb': 0,
|
||||||
'reserved_percentage': 0}]}
|
'reserved_percentage': 0}]}
|
||||||
|
|
||||||
@ -279,7 +279,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
capab1 = {'pools': [{
|
capab1 = {'pools': [{
|
||||||
'pool_name': 'pool1', 'thick_provisioning_support': True,
|
'pool_name': 'pool1', 'thick_provisioning_support': True,
|
||||||
'thin_provisioning_support': False, 'total_capacity_gb': 10,
|
'thin_provisioning_support': False, 'total_capacity_gb': 10,
|
||||||
'free_capacity_gb': 10, 'max_over_subscription_ratio': 1,
|
'free_capacity_gb': 10, 'max_over_subscription_ratio': '1',
|
||||||
'provisioned_capacity_gb': 0, 'allocated_capacity_gb': 0,
|
'provisioned_capacity_gb': 0, 'allocated_capacity_gb': 0,
|
||||||
'reserved_percentage': 0}]}
|
'reserved_percentage': 0}]}
|
||||||
|
|
||||||
@ -348,7 +348,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
capab1 = {'pools': [{
|
capab1 = {'pools': [{
|
||||||
'pool_name': 'pool1', 'thick_provisioning_support': True,
|
'pool_name': 'pool1', 'thick_provisioning_support': True,
|
||||||
'thin_provisioning_support': False, 'total_capacity_gb': 10,
|
'thin_provisioning_support': False, 'total_capacity_gb': 10,
|
||||||
'free_capacity_gb': 10, 'max_over_subscription_ratio': 1,
|
'free_capacity_gb': 10, 'max_over_subscription_ratio': '1',
|
||||||
'provisioned_capacity_gb': 0, 'allocated_capacity_gb': 0,
|
'provisioned_capacity_gb': 0, 'allocated_capacity_gb': 0,
|
||||||
'reserved_percentage': 0}]}
|
'reserved_percentage': 0}]}
|
||||||
|
|
||||||
@ -364,7 +364,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
capab2 = {'pools': [{
|
capab2 = {'pools': [{
|
||||||
'pool_name': 'pool1', 'thick_provisioning_support': True,
|
'pool_name': 'pool1', 'thick_provisioning_support': True,
|
||||||
'thin_provisioning_support': False, 'total_capacity_gb': 10,
|
'thin_provisioning_support': False, 'total_capacity_gb': 10,
|
||||||
'free_capacity_gb': 9, 'max_over_subscription_ratio': 1,
|
'free_capacity_gb': 9, 'max_over_subscription_ratio': '1',
|
||||||
'provisioned_capacity_gb': 1, 'allocated_capacity_gb': 1,
|
'provisioned_capacity_gb': 1, 'allocated_capacity_gb': 1,
|
||||||
'reserved_percentage': 0}]}
|
'reserved_percentage': 0}]}
|
||||||
|
|
||||||
@ -423,14 +423,14 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
capab1 = {'pools': [{
|
capab1 = {'pools': [{
|
||||||
'pool_name': 'pool1', 'thick_provisioning_support': True,
|
'pool_name': 'pool1', 'thick_provisioning_support': True,
|
||||||
'thin_provisioning_support': False, 'total_capacity_gb': 10,
|
'thin_provisioning_support': False, 'total_capacity_gb': 10,
|
||||||
'free_capacity_gb': 10, 'max_over_subscription_ratio': 1,
|
'free_capacity_gb': 10, 'max_over_subscription_ratio': '1',
|
||||||
'provisioned_capacity_gb': 0, 'allocated_capacity_gb': 0,
|
'provisioned_capacity_gb': 0, 'allocated_capacity_gb': 0,
|
||||||
'reserved_percentage': 0}]}
|
'reserved_percentage': 0}]}
|
||||||
|
|
||||||
capab2 = {'pools': [{
|
capab2 = {'pools': [{
|
||||||
'pool_name': 'pool1', 'thick_provisioning_support': True,
|
'pool_name': 'pool1', 'thick_provisioning_support': True,
|
||||||
'thin_provisioning_support': False, 'total_capacity_gb': 10,
|
'thin_provisioning_support': False, 'total_capacity_gb': 10,
|
||||||
'free_capacity_gb': 9, 'max_over_subscription_ratio': 1,
|
'free_capacity_gb': 9, 'max_over_subscription_ratio': '1',
|
||||||
'provisioned_capacity_gb': 1, 'allocated_capacity_gb': 1,
|
'provisioned_capacity_gb': 1, 'allocated_capacity_gb': 1,
|
||||||
'reserved_percentage': 0}]}
|
'reserved_percentage': 0}]}
|
||||||
|
|
||||||
@ -862,7 +862,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'free_capacity_gb': 28.01,
|
'free_capacity_gb': 28.01,
|
||||||
'allocated_capacity_gb': 2.0,
|
'allocated_capacity_gb': 2.0,
|
||||||
'provisioned_capacity_gb': 2.0,
|
'provisioned_capacity_gb': 2.0,
|
||||||
'max_over_subscription_ratio': 1.0,
|
'max_over_subscription_ratio': '1.0',
|
||||||
'thin_provisioning_support': False,
|
'thin_provisioning_support': False,
|
||||||
'thick_provisioning_support': True,
|
'thick_provisioning_support': True,
|
||||||
'reserved_percentage': 5},
|
'reserved_percentage': 5},
|
||||||
@ -871,7 +871,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'free_capacity_gb': 18.01,
|
'free_capacity_gb': 18.01,
|
||||||
'allocated_capacity_gb': 2.0,
|
'allocated_capacity_gb': 2.0,
|
||||||
'provisioned_capacity_gb': 2.0,
|
'provisioned_capacity_gb': 2.0,
|
||||||
'max_over_subscription_ratio': 2.0,
|
'max_over_subscription_ratio': '2.0',
|
||||||
'thin_provisioning_support': True,
|
'thin_provisioning_support': True,
|
||||||
'thick_provisioning_support': False,
|
'thick_provisioning_support': False,
|
||||||
'reserved_percentage': 5}]}
|
'reserved_percentage': 5}]}
|
||||||
@ -881,7 +881,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'free_capacity_gb': 28.01,
|
'free_capacity_gb': 28.01,
|
||||||
'allocated_capacity_gb': 2.0,
|
'allocated_capacity_gb': 2.0,
|
||||||
'provisioned_capacity_gb': 2.0,
|
'provisioned_capacity_gb': 2.0,
|
||||||
'max_over_subscription_ratio': 1.0,
|
'max_over_subscription_ratio': '1.0',
|
||||||
'thin_provisioning_support': False,
|
'thin_provisioning_support': False,
|
||||||
'thick_provisioning_support': True,
|
'thick_provisioning_support': True,
|
||||||
'reserved_percentage': 5},
|
'reserved_percentage': 5},
|
||||||
@ -890,7 +890,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'free_capacity_gb': 18.01,
|
'free_capacity_gb': 18.01,
|
||||||
'allocated_capacity_gb': 2.0,
|
'allocated_capacity_gb': 2.0,
|
||||||
'provisioned_capacity_gb': 2.0,
|
'provisioned_capacity_gb': 2.0,
|
||||||
'max_over_subscription_ratio': 2.0,
|
'max_over_subscription_ratio': '2.0',
|
||||||
'thin_provisioning_support': True,
|
'thin_provisioning_support': True,
|
||||||
'thick_provisioning_support': False,
|
'thick_provisioning_support': False,
|
||||||
'reserved_percentage': 5}]
|
'reserved_percentage': 5}]
|
||||||
@ -901,7 +901,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'free_capacity_gb': 28.01,
|
'free_capacity_gb': 28.01,
|
||||||
'allocated_capacity_gb': 2.0,
|
'allocated_capacity_gb': 2.0,
|
||||||
'provisioned_capacity_gb': 2.0,
|
'provisioned_capacity_gb': 2.0,
|
||||||
'max_over_subscription_ratio': 2.0,
|
'max_over_subscription_ratio': '2.0',
|
||||||
'thin_provisioning_support': True,
|
'thin_provisioning_support': True,
|
||||||
'thick_provisioning_support': False,
|
'thick_provisioning_support': False,
|
||||||
'reserved_percentage': 0},
|
'reserved_percentage': 0},
|
||||||
@ -910,7 +910,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'free_capacity_gb': 18.01,
|
'free_capacity_gb': 18.01,
|
||||||
'allocated_capacity_gb': 2.0,
|
'allocated_capacity_gb': 2.0,
|
||||||
'provisioned_capacity_gb': 2.0,
|
'provisioned_capacity_gb': 2.0,
|
||||||
'max_over_subscription_ratio': 2.0,
|
'max_over_subscription_ratio': '2.0',
|
||||||
'thin_provisioning_support': True,
|
'thin_provisioning_support': True,
|
||||||
'thick_provisioning_support': False,
|
'thick_provisioning_support': False,
|
||||||
'reserved_percentage': 5}]}
|
'reserved_percentage': 5}]}
|
||||||
@ -920,7 +920,7 @@ class HostManagerTestCase(test.TestCase):
|
|||||||
'free_capacity_gb': 28.01,
|
'free_capacity_gb': 28.01,
|
||||||
'allocated_capacity_gb': 2.0,
|
'allocated_capacity_gb': 2.0,
|
||||||
'provisioned_capacity_gb': 2.0,
|
'provisioned_capacity_gb': 2.0,
|
||||||
'max_over_subscription_ratio': 2.0,
|
'max_over_subscription_ratio': '2.0',
|
||||||
'thin_provisioning_support': True,
|
'thin_provisioning_support': True,
|
||||||
'thick_provisioning_support': False,
|
'thick_provisioning_support': False,
|
||||||
'reserved_percentage': 0}]
|
'reserved_percentage': 0}]
|
||||||
|
@ -34,6 +34,19 @@ from cinder import test
|
|||||||
from cinder.tests.unit import fake_constants as fake
|
from cinder.tests.unit import fake_constants as fake
|
||||||
from cinder import utils
|
from cinder import utils
|
||||||
|
|
||||||
|
POOL_CAPS = {'total_capacity_gb': 0,
|
||||||
|
'free_capacity_gb': 0,
|
||||||
|
'allocated_capacity_gb': 0,
|
||||||
|
'provisioned_capacity_gb': 0,
|
||||||
|
'max_over_subscription_ratio': '1.0',
|
||||||
|
'thin_provisioning_support': False,
|
||||||
|
'thick_provisioning_support': True,
|
||||||
|
'reserved_percentage': 0,
|
||||||
|
'volume_backend_name': 'lvm1',
|
||||||
|
'timestamp': timeutils.utcnow(),
|
||||||
|
'multiattach': True,
|
||||||
|
'uuid': 'a3a593da-7f8d-4bb7-8b4c-f2bc1e0b4824'}
|
||||||
|
|
||||||
|
|
||||||
class ExecuteTestCase(test.TestCase):
|
class ExecuteTestCase(test.TestCase):
|
||||||
@mock.patch('cinder.utils.processutils.execute')
|
@mock.patch('cinder.utils.processutils.execute')
|
||||||
@ -1532,3 +1545,82 @@ class TestCheckMetadataProperties(test.TestCase):
|
|||||||
self.assertRaises(exception.InvalidInput,
|
self.assertRaises(exception.InvalidInput,
|
||||||
utils.check_metadata_properties,
|
utils.check_metadata_properties,
|
||||||
meta)
|
meta)
|
||||||
|
|
||||||
|
|
||||||
|
POOL_CAP1 = {'allocated_capacity_gb': 10, 'provisioned_capacity_gb': 10,
|
||||||
|
'thin_provisioning_support': False, 'total_capacity_gb': 10,
|
||||||
|
'free_capacity_gb': 10, 'max_over_subscription_ratio': 1.0}
|
||||||
|
POOL_CAP2 = {'allocated_capacity_gb': 10, 'provisioned_capacity_gb': 10,
|
||||||
|
'thin_provisioning_support': True, 'total_capacity_gb': 100,
|
||||||
|
'free_capacity_gb': 95, 'max_over_subscription_ratio': None}
|
||||||
|
POOL_CAP3 = {'allocated_capacity_gb': 0, 'provisioned_capacity_gb': 0,
|
||||||
|
'thin_provisioning_support': True, 'total_capacity_gb': 100,
|
||||||
|
'free_capacity_gb': 100, 'max_over_subscription_ratio': 'auto'}
|
||||||
|
POOL_CAP4 = {'allocated_capacity_gb': 100,
|
||||||
|
'thin_provisioning_support': True, 'total_capacity_gb': 2500,
|
||||||
|
'free_capacity_gb': 500, 'max_over_subscription_ratio': 'auto'}
|
||||||
|
POOL_CAP5 = {'allocated_capacity_gb': 10000,
|
||||||
|
'thin_provisioning_support': True, 'total_capacity_gb': 2500,
|
||||||
|
'free_capacity_gb': 0.1, 'max_over_subscription_ratio': 'auto'}
|
||||||
|
POOL_CAP6 = {'allocated_capacity_gb': 1000, 'provisioned_capacity_gb': 1010,
|
||||||
|
'thin_provisioning_support': True, 'total_capacity_gb': 2500,
|
||||||
|
'free_capacity_gb': 2500, 'max_over_subscription_ratio': 'auto'}
|
||||||
|
POOL_CAP7 = {'allocated_capacity_gb': 10, 'provisioned_capacity_gb': 10,
|
||||||
|
'thin_provisioning_support': True, 'total_capacity_gb': 10,
|
||||||
|
'free_capacity_gb': 10}
|
||||||
|
POOL_CAP8 = {'allocated_capacity_gb': 10, 'provisioned_capacity_gb': 10,
|
||||||
|
'thin_provisioning_support': True, 'total_capacity_gb': 10,
|
||||||
|
'free_capacity_gb': 10, 'max_over_subscription_ratio': '15.5'}
|
||||||
|
POOL_CAP9 = {'allocated_capacity_gb': 10, 'provisioned_capacity_gb': 10,
|
||||||
|
'thin_provisioning_support': True, 'total_capacity_gb': 10,
|
||||||
|
'free_capacity_gb': 'unknown',
|
||||||
|
'max_over_subscription_ratio': '15.5'}
|
||||||
|
POOL_CAP10 = {'allocated_capacity_gb': 10, 'provisioned_capacity_gb': 10,
|
||||||
|
'thin_provisioning_support': True,
|
||||||
|
'total_capacity_gb': 'infinite', 'free_capacity_gb': 10,
|
||||||
|
'max_over_subscription_ratio': '15.5'}
|
||||||
|
|
||||||
|
|
||||||
|
@ddt.ddt
|
||||||
|
class TestAutoMaxOversubscriptionRatio(test.TestCase):
|
||||||
|
@ddt.data({'data': POOL_CAP1,
|
||||||
|
'global_max_over_subscription_ratio': 'auto',
|
||||||
|
'expected_result': 1.0},
|
||||||
|
{'data': POOL_CAP2,
|
||||||
|
'global_max_over_subscription_ratio': 'auto',
|
||||||
|
'expected_result': 2.67},
|
||||||
|
{'data': POOL_CAP3,
|
||||||
|
'global_max_over_subscription_ratio': '20.0',
|
||||||
|
'expected_result': 20},
|
||||||
|
{'data': POOL_CAP4,
|
||||||
|
'global_max_over_subscription_ratio': '20.0',
|
||||||
|
'expected_result': 1.05},
|
||||||
|
{'data': POOL_CAP5,
|
||||||
|
'global_max_over_subscription_ratio': '10.0',
|
||||||
|
'expected_result': 5.0},
|
||||||
|
{'data': POOL_CAP6,
|
||||||
|
'global_max_over_subscription_ratio': '20.0',
|
||||||
|
'expected_result': 1011.0},
|
||||||
|
{'data': POOL_CAP7,
|
||||||
|
'global_max_over_subscription_ratio': 'auto',
|
||||||
|
'expected_result': 11.0},
|
||||||
|
{'data': POOL_CAP8,
|
||||||
|
'global_max_over_subscription_ratio': '20.0',
|
||||||
|
'expected_result': 15.5},
|
||||||
|
{'data': POOL_CAP9,
|
||||||
|
'global_max_over_subscription_ratio': '20.0',
|
||||||
|
'expected_result': 1.0},
|
||||||
|
{'data': POOL_CAP10,
|
||||||
|
'global_max_over_subscription_ratio': '20.0',
|
||||||
|
'expected_result': 1.0},
|
||||||
|
)
|
||||||
|
@ddt.unpack
|
||||||
|
def test_calculate_max_over_subscription_ratio(
|
||||||
|
self, data, expected_result, global_max_over_subscription_ratio):
|
||||||
|
|
||||||
|
result = utils.calculate_max_over_subscription_ratio(
|
||||||
|
data, global_max_over_subscription_ratio)
|
||||||
|
# Just for sake of testing we reduce the float precision
|
||||||
|
if result is not None:
|
||||||
|
result = round(result, 2)
|
||||||
|
self.assertEqual(expected_result, result)
|
||||||
|
@ -1055,3 +1055,28 @@ class VolumeUtilsTestCase(test.TestCase):
|
|||||||
group = fake_group.fake_group_obj(
|
group = fake_group.fake_group_obj(
|
||||||
None, group_type_id=fake.GROUP_TYPE_ID)
|
None, group_type_id=fake.GROUP_TYPE_ID)
|
||||||
self.assertTrue(volume_utils.is_group_a_cg_snapshot_type(group))
|
self.assertTrue(volume_utils.is_group_a_cg_snapshot_type(group))
|
||||||
|
|
||||||
|
@ddt.data({'max_over_subscription_ratio': '10', 'supports_auto': True},
|
||||||
|
{'max_over_subscription_ratio': 'auto', 'supports_auto': True},
|
||||||
|
{'max_over_subscription_ratio': 'auto', 'supports_auto': False},
|
||||||
|
{'max_over_subscription_ratio': '1.2', 'supports_auto': False},)
|
||||||
|
@ddt.unpack
|
||||||
|
def test_get_max_over_subscription_ratio(self,
|
||||||
|
max_over_subscription_ratio,
|
||||||
|
supports_auto):
|
||||||
|
|
||||||
|
if not supports_auto and max_over_subscription_ratio == 'auto':
|
||||||
|
self.assertRaises(exception.VolumeDriverException,
|
||||||
|
volume_utils.get_max_over_subscription_ratio,
|
||||||
|
max_over_subscription_ratio, supports_auto)
|
||||||
|
elif not supports_auto:
|
||||||
|
mosr = volume_utils.get_max_over_subscription_ratio(
|
||||||
|
max_over_subscription_ratio, supports_auto)
|
||||||
|
self.assertEqual(float(max_over_subscription_ratio), mosr)
|
||||||
|
else: # supports_auto
|
||||||
|
mosr = volume_utils.get_max_over_subscription_ratio(
|
||||||
|
max_over_subscription_ratio, supports_auto)
|
||||||
|
if max_over_subscription_ratio == 'auto':
|
||||||
|
self.assertEqual(max_over_subscription_ratio, mosr)
|
||||||
|
else:
|
||||||
|
self.assertEqual(float(max_over_subscription_ratio), mosr)
|
||||||
|
@ -1007,7 +1007,7 @@ class FakeXML(object):
|
|||||||
class VMAXUtilsTest(test.TestCase):
|
class VMAXUtilsTest(test.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.data = VMAXCommonData()
|
self.data = VMAXCommonData()
|
||||||
|
volume_utils.get_max_over_subscription_ratio = mock.Mock()
|
||||||
super(VMAXUtilsTest, self).setUp()
|
super(VMAXUtilsTest, self).setUp()
|
||||||
config_group = 'UtilsTests'
|
config_group = 'UtilsTests'
|
||||||
fake_xml = FakeXML().create_fake_config_file(
|
fake_xml = FakeXML().create_fake_config_file(
|
||||||
@ -1487,6 +1487,7 @@ class VMAXRestTest(test.TestCase):
|
|||||||
self.data = VMAXCommonData()
|
self.data = VMAXCommonData()
|
||||||
|
|
||||||
super(VMAXRestTest, self).setUp()
|
super(VMAXRestTest, self).setUp()
|
||||||
|
volume_utils.get_max_over_subscription_ratio = mock.Mock()
|
||||||
config_group = 'RestTests'
|
config_group = 'RestTests'
|
||||||
fake_xml = FakeXML().create_fake_config_file(
|
fake_xml = FakeXML().create_fake_config_file(
|
||||||
config_group, self.data.port_group_name_f)
|
config_group, self.data.port_group_name_f)
|
||||||
@ -2865,6 +2866,7 @@ class VMAXProvisionTest(test.TestCase):
|
|||||||
self.data = VMAXCommonData()
|
self.data = VMAXCommonData()
|
||||||
|
|
||||||
super(VMAXProvisionTest, self).setUp()
|
super(VMAXProvisionTest, self).setUp()
|
||||||
|
volume_utils.get_max_over_subscription_ratio = mock.Mock()
|
||||||
config_group = 'ProvisionTests'
|
config_group = 'ProvisionTests'
|
||||||
self.fake_xml = FakeXML().create_fake_config_file(
|
self.fake_xml = FakeXML().create_fake_config_file(
|
||||||
config_group, self.data.port_group_name_i)
|
config_group, self.data.port_group_name_i)
|
||||||
@ -3367,6 +3369,8 @@ class VMAXCommonTest(test.TestCase):
|
|||||||
self.data = VMAXCommonData()
|
self.data = VMAXCommonData()
|
||||||
|
|
||||||
super(VMAXCommonTest, self).setUp()
|
super(VMAXCommonTest, self).setUp()
|
||||||
|
self.mock_object(volume_utils, 'get_max_over_subscription_ratio',
|
||||||
|
return_value=1.0)
|
||||||
config_group = 'CommonTests'
|
config_group = 'CommonTests'
|
||||||
self.fake_xml = FakeXML().create_fake_config_file(
|
self.fake_xml = FakeXML().create_fake_config_file(
|
||||||
config_group, self.data.port_group_name_f)
|
config_group, self.data.port_group_name_f)
|
||||||
@ -5075,6 +5079,7 @@ class VMAXFCTest(test.TestCase):
|
|||||||
|
|
||||||
super(VMAXFCTest, self).setUp()
|
super(VMAXFCTest, self).setUp()
|
||||||
config_group = 'FCTests'
|
config_group = 'FCTests'
|
||||||
|
volume_utils.get_max_over_subscription_ratio = mock.Mock()
|
||||||
self.fake_xml = FakeXML().create_fake_config_file(
|
self.fake_xml = FakeXML().create_fake_config_file(
|
||||||
config_group, self.data.port_group_name_f)
|
config_group, self.data.port_group_name_f)
|
||||||
self.configuration = FakeConfiguration(self.fake_xml, config_group)
|
self.configuration = FakeConfiguration(self.fake_xml, config_group)
|
||||||
@ -5334,6 +5339,7 @@ class VMAXISCSITest(test.TestCase):
|
|||||||
config_group = 'ISCSITests'
|
config_group = 'ISCSITests'
|
||||||
self.fake_xml = FakeXML().create_fake_config_file(
|
self.fake_xml = FakeXML().create_fake_config_file(
|
||||||
config_group, self.data.port_group_name_i)
|
config_group, self.data.port_group_name_i)
|
||||||
|
volume_utils.get_max_over_subscription_ratio = mock.Mock()
|
||||||
configuration = FakeConfiguration(self.fake_xml, config_group)
|
configuration = FakeConfiguration(self.fake_xml, config_group)
|
||||||
rest.VMAXRest._establish_rest_session = mock.Mock(
|
rest.VMAXRest._establish_rest_session = mock.Mock(
|
||||||
return_value=FakeRequestsSession())
|
return_value=FakeRequestsSession())
|
||||||
@ -5639,6 +5645,7 @@ class VMAXMaskingTest(test.TestCase):
|
|||||||
|
|
||||||
super(VMAXMaskingTest, self).setUp()
|
super(VMAXMaskingTest, self).setUp()
|
||||||
|
|
||||||
|
volume_utils.get_max_over_subscription_ratio = mock.Mock()
|
||||||
configuration = mock.Mock()
|
configuration = mock.Mock()
|
||||||
configuration.safe_get.return_value = 'MaskingTests'
|
configuration.safe_get.return_value = 'MaskingTests'
|
||||||
configuration.config_group = 'MaskingTests'
|
configuration.config_group = 'MaskingTests'
|
||||||
@ -6568,6 +6575,7 @@ class VMAXCommonReplicationTest(test.TestCase):
|
|||||||
'remote_pool': self.data.srp2,
|
'remote_pool': self.data.srp2,
|
||||||
'rdf_group_label': self.data.rdf_group_name,
|
'rdf_group_label': self.data.rdf_group_name,
|
||||||
'allow_extend': 'True'}
|
'allow_extend': 'True'}
|
||||||
|
volume_utils.get_max_over_subscription_ratio = mock.Mock()
|
||||||
configuration = FakeConfiguration(
|
configuration = FakeConfiguration(
|
||||||
self.fake_xml, config_group,
|
self.fake_xml, config_group,
|
||||||
replication_device=self.replication_device)
|
replication_device=self.replication_device)
|
||||||
|
@ -33,6 +33,7 @@ from cinder.tests.unit import fake_volume
|
|||||||
from cinder.volume import configuration as conf
|
from cinder.volume import configuration as conf
|
||||||
from cinder.volume.drivers import nfs
|
from cinder.volume.drivers import nfs
|
||||||
from cinder.volume.drivers import remotefs
|
from cinder.volume.drivers import remotefs
|
||||||
|
from cinder.volume import utils as vutils
|
||||||
|
|
||||||
|
|
||||||
class RemoteFsDriverTestCase(test.TestCase):
|
class RemoteFsDriverTestCase(test.TestCase):
|
||||||
@ -414,6 +415,9 @@ class NfsDriverTestCase(test.TestCase):
|
|||||||
self.configuration.nas_mount_options = None
|
self.configuration.nas_mount_options = None
|
||||||
self.configuration.volume_dd_blocksize = '1M'
|
self.configuration.volume_dd_blocksize = '1M'
|
||||||
|
|
||||||
|
self.mock_object(vutils, 'get_max_over_subscription_ratio',
|
||||||
|
return_value=1)
|
||||||
|
|
||||||
self.context = context.get_admin_context()
|
self.context = context.get_admin_context()
|
||||||
|
|
||||||
def _set_driver(self, extra_confs=None):
|
def _set_driver(self, extra_confs=None):
|
||||||
|
@ -27,6 +27,7 @@ from cinder.tests.unit import fake_constants as fake
|
|||||||
from cinder.tests.unit import fake_group
|
from cinder.tests.unit import fake_group
|
||||||
from cinder.tests.unit import fake_snapshot
|
from cinder.tests.unit import fake_snapshot
|
||||||
from cinder.tests.unit import fake_volume
|
from cinder.tests.unit import fake_volume
|
||||||
|
from cinder.volume import utils as volume_utis
|
||||||
|
|
||||||
|
|
||||||
def fake_retry(exceptions, interval=1, retries=3, backoff_rate=2):
|
def fake_retry(exceptions, interval=1, retries=3, backoff_rate=2):
|
||||||
@ -2688,6 +2689,8 @@ class PureVolumeUpdateStatsTestCase(PureBaseSharedDriverTestCase):
|
|||||||
config_ratio,
|
config_ratio,
|
||||||
expected_ratio,
|
expected_ratio,
|
||||||
auto):
|
auto):
|
||||||
|
volume_utis.get_max_over_subscription_ratio = mock.Mock(
|
||||||
|
return_value=expected_ratio)
|
||||||
self.mock_config.pure_automatic_max_oversubscription_ratio = auto
|
self.mock_config.pure_automatic_max_oversubscription_ratio = auto
|
||||||
self.mock_config.max_over_subscription_ratio = config_ratio
|
self.mock_config.max_over_subscription_ratio = config_ratio
|
||||||
actual_ratio = self.driver._get_thin_provisioning(provisioned, used)
|
actual_ratio = self.driver._get_thin_provisioning(provisioned, used)
|
||||||
|
@ -37,6 +37,7 @@ from cinder.volume.drivers.zfssa import webdavclient
|
|||||||
from cinder.volume.drivers.zfssa import zfssaiscsi as iscsi
|
from cinder.volume.drivers.zfssa import zfssaiscsi as iscsi
|
||||||
from cinder.volume.drivers.zfssa import zfssanfs
|
from cinder.volume.drivers.zfssa import zfssanfs
|
||||||
from cinder.volume.drivers.zfssa import zfssarest as rest
|
from cinder.volume.drivers.zfssa import zfssarest as rest
|
||||||
|
from cinder.volume import utils as volume_utils
|
||||||
|
|
||||||
|
|
||||||
nfs_logbias = 'latency'
|
nfs_logbias = 'latency'
|
||||||
@ -137,6 +138,8 @@ class TestZFSSAISCSIDriver(test.TestCase):
|
|||||||
def setUp(self, _factory_zfssa):
|
def setUp(self, _factory_zfssa):
|
||||||
super(TestZFSSAISCSIDriver, self).setUp()
|
super(TestZFSSAISCSIDriver, self).setUp()
|
||||||
self._create_fake_config()
|
self._create_fake_config()
|
||||||
|
self.mock_object(volume_utils, 'get_max_over_subscription_ratio',
|
||||||
|
return_value=1.0)
|
||||||
_factory_zfssa.return_value = mock.MagicMock(spec=rest.ZFSSAApi)
|
_factory_zfssa.return_value = mock.MagicMock(spec=rest.ZFSSAApi)
|
||||||
iscsi.ZFSSAISCSIDriver._execute = fake_utils.fake_execute
|
iscsi.ZFSSAISCSIDriver._execute = fake_utils.fake_execute
|
||||||
self.drv = iscsi.ZFSSAISCSIDriver(configuration=self.configuration)
|
self.drv = iscsi.ZFSSAISCSIDriver(configuration=self.configuration)
|
||||||
@ -1038,6 +1041,8 @@ class TestZFSSANFSDriver(test.TestCase):
|
|||||||
super(TestZFSSANFSDriver, self).setUp()
|
super(TestZFSSANFSDriver, self).setUp()
|
||||||
self._create_fake_config()
|
self._create_fake_config()
|
||||||
_factory_zfssa.return_value = mock.MagicMock(spec=rest.ZFSSANfsApi)
|
_factory_zfssa.return_value = mock.MagicMock(spec=rest.ZFSSANfsApi)
|
||||||
|
self.mock_object(volume_utils, 'get_max_over_subscription_ratio',
|
||||||
|
return_value=1.0)
|
||||||
self.drv = zfssanfs.ZFSSANFSDriver(configuration=self.configuration)
|
self.drv = zfssanfs.ZFSSANFSDriver(configuration=self.configuration)
|
||||||
self.drv._execute = fake_utils.fake_execute
|
self.drv._execute = fake_utils.fake_execute
|
||||||
self.drv.do_setup({})
|
self.drv.do_setup({})
|
||||||
|
@ -562,6 +562,34 @@ class GenericVolumeDriverTestCase(BaseDriverTestCase):
|
|||||||
self.assertTrue(terminate_mock.called)
|
self.assertTrue(terminate_mock.called)
|
||||||
self.assertEqual(3, exc.context.call_count)
|
self.assertEqual(3, exc.context.call_count)
|
||||||
|
|
||||||
|
@ddt.data({'cfg_value': '10', 'valid': True},
|
||||||
|
{'cfg_value': 'auto', 'valid': True},
|
||||||
|
{'cfg_value': '1', 'valid': True},
|
||||||
|
{'cfg_value': '1.2', 'valid': True},
|
||||||
|
{'cfg_value': '100', 'valid': True},
|
||||||
|
{'cfg_value': '20.15', 'valid': True},
|
||||||
|
{'cfg_value': 'True', 'valid': False},
|
||||||
|
{'cfg_value': 'False', 'valid': False},
|
||||||
|
{'cfg_value': '10.0.0', 'valid': False},
|
||||||
|
{'cfg_value': '0.00', 'valid': True},
|
||||||
|
{'cfg_value': 'anything', 'valid': False},)
|
||||||
|
@ddt.unpack
|
||||||
|
def test_auto_max_subscription_ratio_options(self, cfg_value, valid):
|
||||||
|
# This tests the max_over_subscription_ratio option as it is now
|
||||||
|
# checked by a regex
|
||||||
|
def _set_conf(config, value):
|
||||||
|
config.set_override('max_over_subscription_ratio', value)
|
||||||
|
|
||||||
|
config = conf.Configuration(None)
|
||||||
|
config.append_config_values(driver.volume_opts)
|
||||||
|
|
||||||
|
if valid:
|
||||||
|
_set_conf(config, cfg_value)
|
||||||
|
self.assertEqual(cfg_value, config.safe_get(
|
||||||
|
'max_over_subscription_ratio'))
|
||||||
|
else:
|
||||||
|
self.assertRaises(ValueError, _set_conf, config, cfg_value)
|
||||||
|
|
||||||
|
|
||||||
class FibreChannelTestCase(BaseDriverTestCase):
|
class FibreChannelTestCase(BaseDriverTestCase):
|
||||||
"""Test Case for FibreChannelDriver."""
|
"""Test Case for FibreChannelDriver."""
|
||||||
|
@ -64,6 +64,9 @@ PERFECT_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%f"
|
|||||||
VALID_TRACE_FLAGS = {'method', 'api'}
|
VALID_TRACE_FLAGS = {'method', 'api'}
|
||||||
TRACE_METHOD = False
|
TRACE_METHOD = False
|
||||||
TRACE_API = False
|
TRACE_API = False
|
||||||
|
INITIAL_AUTO_MOSR = 20
|
||||||
|
INFINITE_UNKNOWN_VALUES = ('infinite', 'unknown')
|
||||||
|
|
||||||
|
|
||||||
synchronized = lockutils.synchronized_with_prefix('cinder-')
|
synchronized = lockutils.synchronized_with_prefix('cinder-')
|
||||||
|
|
||||||
@ -1044,6 +1047,65 @@ def calculate_virtual_free_capacity(total_capacity,
|
|||||||
return free
|
return free
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_max_over_subscription_ratio(capability,
|
||||||
|
global_max_over_subscription_ratio):
|
||||||
|
# provisioned_capacity_gb is the apparent total capacity of
|
||||||
|
# all the volumes created on a backend, which is greater than
|
||||||
|
# or equal to allocated_capacity_gb, which is the apparent
|
||||||
|
# total capacity of all the volumes created on a backend
|
||||||
|
# in Cinder. Using allocated_capacity_gb as the default of
|
||||||
|
# provisioned_capacity_gb if it is not set.
|
||||||
|
allocated_capacity_gb = capability.get('allocated_capacity_gb', 0)
|
||||||
|
provisioned_capacity_gb = capability.get('provisioned_capacity_gb',
|
||||||
|
allocated_capacity_gb)
|
||||||
|
thin_provisioning_support = capability.get('thin_provisioning_support',
|
||||||
|
False)
|
||||||
|
total_capacity_gb = capability.get('total_capacity_gb', 0)
|
||||||
|
free_capacity_gb = capability.get('free_capacity_gb', 0)
|
||||||
|
pool_name = capability.get('pool_name',
|
||||||
|
capability.get('volume_backend_name'))
|
||||||
|
|
||||||
|
# If thin provisioning is not supported the capacity filter will not use
|
||||||
|
# the value we return, no matter what it is.
|
||||||
|
if not thin_provisioning_support:
|
||||||
|
LOG.debug("Trying to retrieve max_over_subscription_ratio from a "
|
||||||
|
"service that does not support thin provisioning")
|
||||||
|
return 1.0
|
||||||
|
|
||||||
|
# Again, if total or free capacity is infinite or unknown, the capacity
|
||||||
|
# filter will not use the max_over_subscription_ratio at all. So, does
|
||||||
|
# not matter what we return here.
|
||||||
|
if ((total_capacity_gb in INFINITE_UNKNOWN_VALUES) or
|
||||||
|
(free_capacity_gb in INFINITE_UNKNOWN_VALUES)):
|
||||||
|
return 1.0
|
||||||
|
|
||||||
|
max_over_subscription_ratio = (capability.get(
|
||||||
|
'max_over_subscription_ratio') or global_max_over_subscription_ratio)
|
||||||
|
|
||||||
|
# We only calculate the automatic max_over_subscription_ratio (mosr)
|
||||||
|
# when the global or driver conf is set auto and while
|
||||||
|
# provisioned_capacity_gb is not 0. When auto is set and
|
||||||
|
# provisioned_capacity_gb is 0, we use the default value 20.0.
|
||||||
|
if max_over_subscription_ratio == 'auto':
|
||||||
|
if provisioned_capacity_gb != 0:
|
||||||
|
used_capacity = total_capacity_gb - free_capacity_gb
|
||||||
|
LOG.debug("Calculating max_over_subscription_ratio for "
|
||||||
|
"pool %s: provisioned_capacity_gb=%s, "
|
||||||
|
"used_capacity=%s",
|
||||||
|
pool_name, provisioned_capacity_gb, used_capacity)
|
||||||
|
max_over_subscription_ratio = 1 + (
|
||||||
|
float(provisioned_capacity_gb) / (used_capacity + 1))
|
||||||
|
else:
|
||||||
|
max_over_subscription_ratio = INITIAL_AUTO_MOSR
|
||||||
|
|
||||||
|
LOG.info("Auto max_over_subscription_ratio for pool %s is "
|
||||||
|
"%s", pool_name, max_over_subscription_ratio)
|
||||||
|
else:
|
||||||
|
max_over_subscription_ratio = float(max_over_subscription_ratio)
|
||||||
|
|
||||||
|
return max_over_subscription_ratio
|
||||||
|
|
||||||
|
|
||||||
def validate_integer(value, name, min_value=None, max_value=None):
|
def validate_integer(value, name, min_value=None, max_value=None):
|
||||||
"""Make sure that value is a valid integer, potentially within range.
|
"""Make sure that value is a valid integer, potentially within range.
|
||||||
|
|
||||||
|
@ -162,17 +162,20 @@ volume_opts = [
|
|||||||
default=False,
|
default=False,
|
||||||
help='Tell driver to use SSL for connection to backend '
|
help='Tell driver to use SSL for connection to backend '
|
||||||
'storage if the driver supports it.'),
|
'storage if the driver supports it.'),
|
||||||
cfg.FloatOpt('max_over_subscription_ratio',
|
cfg.StrOpt('max_over_subscription_ratio',
|
||||||
default=20.0,
|
default='20.0',
|
||||||
min=1,
|
regex='^(auto|\d*\.\d+|\d+)$',
|
||||||
help='Float representation of the over subscription ratio '
|
help='Representation of the over subscription ratio '
|
||||||
'when thin provisioning is involved. Default ratio is '
|
'when thin provisioning is enabled. Default ratio is '
|
||||||
'20.0, meaning provisioned capacity can be 20 times of '
|
'20.0, meaning provisioned capacity can be 20 times of '
|
||||||
'the total physical capacity. If the ratio is 10.5, it '
|
'the total physical capacity. If the ratio is 10.5, it '
|
||||||
'means provisioned capacity can be 10.5 times of the '
|
'means provisioned capacity can be 10.5 times of the '
|
||||||
'total physical capacity. A ratio of 1.0 means '
|
'total physical capacity. A ratio of 1.0 means '
|
||||||
'provisioned capacity cannot exceed the total physical '
|
'provisioned capacity cannot exceed the total physical '
|
||||||
'capacity. The ratio has to be a minimum of 1.0.'),
|
'capacity. If ratio is \'auto\', Cinder will '
|
||||||
|
'automatically calculate the ratio based on the '
|
||||||
|
'provisioned capacity and the used space. If not set to '
|
||||||
|
'auto, the ratio has to be a minimum of 1.0.'),
|
||||||
cfg.StrOpt('scst_target_iqn_name',
|
cfg.StrOpt('scst_target_iqn_name',
|
||||||
help='Certain ISCSI targets have predefined target names, '
|
help='Certain ISCSI targets have predefined target names, '
|
||||||
'SCST target driver uses this name.'),
|
'SCST target driver uses this name.'),
|
||||||
|
@ -149,8 +149,9 @@ class VMAXCommon(object):
|
|||||||
self.retries = self.configuration.safe_get('retries')
|
self.retries = self.configuration.safe_get('retries')
|
||||||
self.pool_info['backend_name'] = (
|
self.pool_info['backend_name'] = (
|
||||||
self.configuration.safe_get('volume_backend_name'))
|
self.configuration.safe_get('volume_backend_name'))
|
||||||
self.pool_info['max_over_subscription_ratio'] = (
|
mosr = volume_utils.get_max_over_subscription_ratio(
|
||||||
self.configuration.safe_get('max_over_subscription_ratio'))
|
self.configuration.safe_get('max_over_subscription_ratio'), True)
|
||||||
|
self.pool_info['max_over_subscription_ratio'] = mosr
|
||||||
self.pool_info['reserved_percentage'] = (
|
self.pool_info['reserved_percentage'] = (
|
||||||
self.configuration.safe_get('reserved_percentage'))
|
self.configuration.safe_get('reserved_percentage'))
|
||||||
LOG.debug(
|
LOG.debug(
|
||||||
@ -888,11 +889,6 @@ class VMAXCommon(object):
|
|||||||
else:
|
else:
|
||||||
pool['reserved_percentage'] = array_reserve_percent
|
pool['reserved_percentage'] = array_reserve_percent
|
||||||
|
|
||||||
if max_oversubscription_ratio and (
|
|
||||||
0.0 < max_oversubscription_ratio < 1):
|
|
||||||
pool['max_over_subscription_ratio'] = (
|
|
||||||
self.utils.get_default_oversubscription_ratio(
|
|
||||||
max_oversubscription_ratio))
|
|
||||||
pools.append(pool)
|
pools.append(pool)
|
||||||
pools = self.utils.add_legacy_pools(pools)
|
pools = self.utils.add_legacy_pools(pools)
|
||||||
data = {'vendor_name': "Dell EMC",
|
data = {'vendor_name': "Dell EMC",
|
||||||
|
@ -54,6 +54,7 @@ from cinder import utils
|
|||||||
from cinder.volume import configuration
|
from cinder.volume import configuration
|
||||||
from cinder.volume import driver
|
from cinder.volume import driver
|
||||||
from cinder.volume.drivers.san import san
|
from cinder.volume.drivers.san import san
|
||||||
|
from cinder.volume import utils as vutils
|
||||||
from cinder.zonemanager import utils as fczm_utils
|
from cinder.zonemanager import utils as fczm_utils
|
||||||
|
|
||||||
|
|
||||||
@ -424,9 +425,10 @@ class XtremIOVolumeDriver(san.SanDriver):
|
|||||||
or self.driver_name)
|
or self.driver_name)
|
||||||
self.cluster_id = (self.configuration.safe_get('xtremio_cluster_name')
|
self.cluster_id = (self.configuration.safe_get('xtremio_cluster_name')
|
||||||
or '')
|
or '')
|
||||||
self.provisioning_factor = (self.configuration.
|
self.provisioning_factor = vutils.get_max_over_subscription_ratio(
|
||||||
safe_get('max_over_subscription_ratio')
|
self.configuration.max_over_subscription_ratio,
|
||||||
or DEFAULT_PROVISIONING_FACTOR)
|
supports_auto=False)
|
||||||
|
|
||||||
self.clean_ig = (self.configuration.safe_get('xtremio_clean_unused_ig')
|
self.clean_ig = (self.configuration.safe_get('xtremio_clean_unused_ig')
|
||||||
or False)
|
or False)
|
||||||
self._stats = {}
|
self._stats = {}
|
||||||
|
@ -798,11 +798,14 @@ class KaminarioCinderDriver(cinder.volume.driver.ISCSIDriver):
|
|||||||
LOG.debug("Searching total volumes in K2 for updating stats.")
|
LOG.debug("Searching total volumes in K2 for updating stats.")
|
||||||
total_volumes = self.client.search("volumes").total - 1
|
total_volumes = self.client.search("volumes").total - 1
|
||||||
provisioned_vol = cap.provisioned_volumes
|
provisioned_vol = cap.provisioned_volumes
|
||||||
|
|
||||||
if (conf.auto_calc_max_oversubscription_ratio and cap.provisioned
|
if (conf.auto_calc_max_oversubscription_ratio and cap.provisioned
|
||||||
and (cap.total - cap.free) != 0):
|
and (cap.total - cap.free) != 0):
|
||||||
ratio = provisioned_vol / float(cap.total - cap.free)
|
ratio = provisioned_vol / float(cap.total - cap.free)
|
||||||
else:
|
else:
|
||||||
ratio = conf.max_over_subscription_ratio
|
ratio = vol_utils.get_max_over_subscription_ratio(
|
||||||
|
conf.max_over_subscription_ratio, supports_auto=True)
|
||||||
|
|
||||||
self.stats = {'QoS_support': False,
|
self.stats = {'QoS_support': False,
|
||||||
'free_capacity_gb': cap.free / units.Mi,
|
'free_capacity_gb': cap.free / units.Mi,
|
||||||
'total_capacity_gb': cap.total / units.Mi,
|
'total_capacity_gb': cap.total / units.Mi,
|
||||||
|
@ -115,7 +115,9 @@ class NetAppBlockStorageLibrary(object):
|
|||||||
na_opts.netapp_provisioning_opts)
|
na_opts.netapp_provisioning_opts)
|
||||||
self.configuration.append_config_values(na_opts.netapp_san_opts)
|
self.configuration.append_config_values(na_opts.netapp_san_opts)
|
||||||
self.max_over_subscription_ratio = (
|
self.max_over_subscription_ratio = (
|
||||||
self.configuration.max_over_subscription_ratio)
|
volume_utils.get_max_over_subscription_ratio(
|
||||||
|
self.configuration.max_over_subscription_ratio,
|
||||||
|
supports_auto=False))
|
||||||
self.reserved_percentage = self._get_reserved_percentage()
|
self.reserved_percentage = self._get_reserved_percentage()
|
||||||
self.loopingcalls = loopingcalls.LoopingCalls()
|
self.loopingcalls = loopingcalls.LoopingCalls()
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ from cinder import interface
|
|||||||
from cinder import utils
|
from cinder import utils
|
||||||
from cinder.volume import configuration
|
from cinder.volume import configuration
|
||||||
from cinder.volume.drivers import remotefs
|
from cinder.volume.drivers import remotefs
|
||||||
|
from cinder.volume import utils as vutils
|
||||||
|
|
||||||
VERSION = '1.4.0'
|
VERSION = '1.4.0'
|
||||||
|
|
||||||
@ -116,7 +117,9 @@ class NfsDriver(remotefs.RemoteFSSnapDriverDistributed):
|
|||||||
self._sparse_copy_volume_data = True
|
self._sparse_copy_volume_data = True
|
||||||
self.reserved_percentage = self.configuration.reserved_percentage
|
self.reserved_percentage = self.configuration.reserved_percentage
|
||||||
self.max_over_subscription_ratio = (
|
self.max_over_subscription_ratio = (
|
||||||
self.configuration.max_over_subscription_ratio)
|
vutils.get_max_over_subscription_ratio(
|
||||||
|
self.configuration.max_over_subscription_ratio,
|
||||||
|
supports_auto=False))
|
||||||
|
|
||||||
def initialize_connection(self, volume, connector):
|
def initialize_connection(self, volume, connector):
|
||||||
|
|
||||||
|
@ -613,6 +613,7 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
a value, if not we will respect the configuration option for the
|
a value, if not we will respect the configuration option for the
|
||||||
max_over_subscription_ratio.
|
max_over_subscription_ratio.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if (self.configuration.pure_automatic_max_oversubscription_ratio and
|
if (self.configuration.pure_automatic_max_oversubscription_ratio and
|
||||||
used_space != 0 and provisioned_space != 0):
|
used_space != 0 and provisioned_space != 0):
|
||||||
# If array is empty we can not calculate a max oversubscription
|
# If array is empty we can not calculate a max oversubscription
|
||||||
@ -622,7 +623,9 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
# presented based on current usage.
|
# presented based on current usage.
|
||||||
thin_provisioning = provisioned_space / used_space
|
thin_provisioning = provisioned_space / used_space
|
||||||
else:
|
else:
|
||||||
thin_provisioning = self.configuration.max_over_subscription_ratio
|
thin_provisioning = volume_utils.get_max_over_subscription_ratio(
|
||||||
|
self.configuration.max_over_subscription_ratio,
|
||||||
|
supports_auto=True)
|
||||||
|
|
||||||
return thin_provisioning
|
return thin_provisioning
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ from cinder.volume import configuration
|
|||||||
from cinder.volume.drivers import nfs
|
from cinder.volume.drivers import nfs
|
||||||
from cinder.volume.drivers.san import san
|
from cinder.volume.drivers.san import san
|
||||||
from cinder.volume.drivers.zfssa import zfssarest
|
from cinder.volume.drivers.zfssa import zfssarest
|
||||||
|
from cinder.volume import utils as vutils
|
||||||
|
|
||||||
|
|
||||||
ZFSSA_OPTS = [
|
ZFSSA_OPTS = [
|
||||||
@ -108,6 +109,11 @@ class ZFSSANFSDriver(nfs.NfsDriver):
|
|||||||
self._stats = None
|
self._stats = None
|
||||||
|
|
||||||
def do_setup(self, context):
|
def do_setup(self, context):
|
||||||
|
self.configuration.max_over_subscription_ratio = (
|
||||||
|
vutils.get_max_over_subscription_ratio(
|
||||||
|
self.configuration.max_over_subscription_ratio,
|
||||||
|
supports_auto=False))
|
||||||
|
|
||||||
if not self.configuration.max_over_subscription_ratio > 0:
|
if not self.configuration.max_over_subscription_ratio > 0:
|
||||||
msg = _("Config 'max_over_subscription_ratio' invalid. Must be > "
|
msg = _("Config 'max_over_subscription_ratio' invalid. Must be > "
|
||||||
"0: %s") % self.configuration.max_over_subscription_ratio
|
"0: %s") % self.configuration.max_over_subscription_ratio
|
||||||
|
@ -980,3 +980,35 @@ def is_group_a_type(group, key):
|
|||||||
)
|
)
|
||||||
return spec == "<is> True"
|
return spec == "<is> True"
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def get_max_over_subscription_ratio(str_value, supports_auto=False):
|
||||||
|
"""Get the max_over_subscription_ratio from a string
|
||||||
|
|
||||||
|
As some drivers need to do some calculations with the value and we are now
|
||||||
|
receiving a string value in the conf, this converts the value to float
|
||||||
|
when appropriate.
|
||||||
|
|
||||||
|
:param str_value: Configuration object
|
||||||
|
:param supports_auto: Tell if the calling driver supports auto MOSR.
|
||||||
|
:param drv_msg: Error message from the caller
|
||||||
|
:response: value of mosr
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not supports_auto and str_value == "auto":
|
||||||
|
msg = _("This driver does not support automatic "
|
||||||
|
"max_over_subscription_ratio calculation. Please use a "
|
||||||
|
"valid float value.")
|
||||||
|
LOG.error(msg)
|
||||||
|
raise exception.VolumeDriverException(message=msg)
|
||||||
|
|
||||||
|
if str_value == 'auto':
|
||||||
|
return str_value
|
||||||
|
|
||||||
|
mosr = float(str_value)
|
||||||
|
if mosr < 1:
|
||||||
|
msg = _("The value of max_over_subscription_ratio must be "
|
||||||
|
"greater than 1.")
|
||||||
|
LOG.error(msg)
|
||||||
|
raise exception.InvalidParameterValue(message=msg)
|
||||||
|
return mosr
|
||||||
|
@ -23,6 +23,13 @@ A ratio of 1.0 means provisioned capacity cannot exceed the total physical
|
|||||||
capacity. A ratio lower than 1.0 is ignored and the default value is used
|
capacity. A ratio lower than 1.0 is ignored and the default value is used
|
||||||
instead.
|
instead.
|
||||||
|
|
||||||
|
This parameter also can be set as ``max_over_subscription_ratio=auto``. When
|
||||||
|
using auto, Cinder will automatically calculate the
|
||||||
|
``max_over_subscription_ratio`` based on the provisioned capacity and the used
|
||||||
|
space. This allows the creation of a larger number of volumes at the
|
||||||
|
begginning of the pool's life, and start to restrict the creation as the free
|
||||||
|
space approaces to 0 or the reserved limit.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
``max_over_subscription_ratio`` can be configured for each back end when
|
``max_over_subscription_ratio`` can be configured for each back end when
|
||||||
@ -34,6 +41,10 @@ instead.
|
|||||||
driver that supports multiple pools per back end, it can report this
|
driver that supports multiple pools per back end, it can report this
|
||||||
ratio for each pool. The LVM driver does not support multiple pools.
|
ratio for each pool. The LVM driver does not support multiple pools.
|
||||||
|
|
||||||
|
Setting this value to 'auto'. The values calculated by Cinder can
|
||||||
|
dinamically vary according to the pool's provisioned capacity and consumed
|
||||||
|
space.
|
||||||
|
|
||||||
The existing ``reserved_percentage`` flag is used to prevent over provisioning.
|
The existing ``reserved_percentage`` flag is used to prevent over provisioning.
|
||||||
This flag represents the percentage of the back-end capacity that is reserved.
|
This flag represents the percentage of the back-end capacity that is reserved.
|
||||||
|
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Cinder now supports the use of 'max_over_subscription_ratio = auto' which
|
||||||
|
automatically calculates the value for max_over_subscription_ratio in the
|
||||||
|
scheduler.
|
Loading…
Reference in New Issue
Block a user