QoS support for shares

QoS is a common attribute, so add the QoS
capability in common capabilities doc.
This is a simple first step towards what the
blueprints proposes.

Partially implements: bp manila-support-qos
Change-Id: I377bf0abcc62239c9a1a5ee5c28c336b2b6c410a
This commit is contained in:
zhongjun 2015-11-19 11:46:14 +08:00
parent 4233429a46
commit 5dfc143909
22 changed files with 55 additions and 43 deletions

View File

@ -85,6 +85,17 @@ be created.
thick. So, a Manila pool will always report thin_provisioning as True or thick. So, a Manila pool will always report thin_provisioning as True or
False. Added in Liberty. False. Added in Liberty.
* `qos` - indicates that a backend/pool can provide shares using some
QoS (Quality of Service) specification. The default value of the qos
capability (if a driver doesn't report it) is False. Administrators
can make a share type use QoS by setting this extra-spec to '<is> True' and
also setting the relevant QoS-related extra specs for the drivers being used.
Administrators can prevent a share type from using QoS by setting this
extra-spec to '<is> False'. Different drivers have different ways of specifying
QoS limits (or guarantees) and this extra spec merely allows the scheduler to
filter by pools that either have or don't have QoS support enabled. Added in
Mitaka.
Reporting Capabilities Reporting Capabilities
---------------------- ----------------------
Drivers report capabilities as part of the updated stats (e.g. capacity) Drivers report capabilities as part of the updated stats (e.g. capacity)
@ -113,15 +124,15 @@ example vendor prefix:
'my_capability_2': True, # stats & capabilities 'my_capability_2': True, # stats & capabilities
#/ #/
'pools': [ 'pools': [
{'pool_name': {'pool_name':
'thin-dedupe-compression pool', #\ 'thin-dedupe-compression pool', #\
'total_capacity_gb': 500, # mandatory stats for 'total_capacity_gb': 500, # mandatory stats for
'free_capacity_gb': 230, # pools 'free_capacity_gb': 230, # pools
'QoS_support': 'False', # |
'reserved_percentage': 0, #/ 'reserved_percentage': 0, #/
#\ #\
'dedupe': True, # common capabilities 'dedupe': True, # common capabilities
'compression': True, # 'compression': True, #
'qos': True, # this backend supports QoS
'thin_provisioning': True, # 'thin_provisioning': True, #
'max_over_subscription_ratio': 10, # (mandatory for thin) 'max_over_subscription_ratio': 10, # (mandatory for thin)
'provisioned_capacity_gb': 270, # (mandatory for thin) 'provisioned_capacity_gb': 270, # (mandatory for thin)
@ -134,7 +145,7 @@ example vendor prefix:
{'pool_name': 'thick pool', {'pool_name': 'thick pool',
'total_capacity_gb': 1024, 'total_capacity_gb': 1024,
'free_capacity_gb': 1024, 'free_capacity_gb': 1024,
'QoS_support': 'False', 'qos': False,
'reserved_percentage': 0, 'reserved_percentage': 0,
'dedupe': False, 'dedupe': False,
'compression': False, 'compression': False,

View File

@ -93,7 +93,8 @@ function correctly in Manila, such as:
- dedupe: whether the backend supports deduplication; - dedupe: whether the backend supports deduplication;
- compression: whether the backend supports compressed shares; - compression: whether the backend supports compressed shares;
- thin_provisioning: whether the backend is overprovisioning shares; - thin_provisioning: whether the backend is overprovisioning shares;
- pools: list of storage pools managed by this driver instance. - pools: list of storage pools managed by this driver instance;
- qos: whether the backend supports quality of service for shares.
.. note:: for more information please see http://docs.openstack.org/developer/manila/devref/capabilities_and_extra_specs.html .. note:: for more information please see http://docs.openstack.org/developer/manila/devref/capabilities_and_extra_specs.html
@ -197,4 +198,4 @@ Shares can be created within Consistency Groups in order to guarantee snapshot
consistency of multiple shares. In order to make use of this feature, driver consistency of multiple shares. In order to make use of this feature, driver
vendors must report this capability and implement its functions to work vendors must report this capability and implement its functions to work
according to the backend, so the feature can be properly invoked through according to the backend, so the feature can be properly invoked through
Manila API. Manila API.

View File

@ -191,7 +191,7 @@ pools:
'total_capacity_gb': 500, # mandatory stats for 'total_capacity_gb': 500, # mandatory stats for
'free_capacity_gb': 230, # pools 'free_capacity_gb': 230, # pools
'allocated_capacity_gb': 270, # | 'allocated_capacity_gb': 270, # |
'QoS_support': 'False', # | 'qos': True, # |
'reserved_percentage': 0, #/ 'reserved_percentage': 0, #/
'dying_disks': 100, #\ 'dying_disks': 100, #\
@ -203,7 +203,7 @@ pools:
'total_capacity_gb': 1024, 'total_capacity_gb': 1024,
'free_capacity_gb': 1024, 'free_capacity_gb': 1024,
'allocated_capacity_gb': 0, 'allocated_capacity_gb': 0,
'QoS_support': 'False', 'qos': False,
'reserved_percentage': 0, 'reserved_percentage': 0,
'dying_disks': 200, 'dying_disks': 200,

View File

@ -108,7 +108,7 @@ class HostState(object):
self.vendor_name = None self.vendor_name = None
self.driver_version = 0 self.driver_version = 0
self.storage_protocol = None self.storage_protocol = None
self.QoS_support = False self.qos = False
# Mutable available resources. # Mutable available resources.
# These will change as resources are virtually "consumed". # These will change as resources are virtually "consumed".
self.total_capacity_gb = 0 self.total_capacity_gb = 0
@ -164,7 +164,7 @@ class HostState(object):
'total_capacity_gb': 500, # mandatory stats for 'total_capacity_gb': 500, # mandatory stats for
'free_capacity_gb': 230, # pools 'free_capacity_gb': 230, # pools
'allocated_capacity_gb': 270, # | 'allocated_capacity_gb': 270, # |
'QoS_support': 'False', # | 'qos': 'False', # |
'reserved_percentage': 0, #/ 'reserved_percentage': 0, #/
'dying_disks': 100, #\ 'dying_disks': 100, #\
@ -176,7 +176,7 @@ class HostState(object):
'total_capacity_gb': 1024, 'total_capacity_gb': 1024,
'free_capacity_gb': 1024, 'free_capacity_gb': 1024,
'allocated_capacity_gb': 0, 'allocated_capacity_gb': 0,
'QoS_support': 'False', 'qos': 'False',
'reserved_percentage': 0, 'reserved_percentage': 0,
'dying_disks': 200, 'dying_disks': 200,
@ -346,7 +346,7 @@ class PoolState(HostState):
self.free_capacity_gb = capability['free_capacity_gb'] self.free_capacity_gb = capability['free_capacity_gb']
self.allocated_capacity_gb = capability.get( self.allocated_capacity_gb = capability.get(
'allocated_capacity_gb', 0) 'allocated_capacity_gb', 0)
self.QoS_support = capability.get('QoS_support', False) self.qos = capability.get('qos', False)
self.reserved_percentage = capability['reserved_percentage'] self.reserved_percentage = capability['reserved_percentage']
# NOTE(xyang): provisioned_capacity_gb is the apparent total # NOTE(xyang): provisioned_capacity_gb is the apparent total
# capacity of all the shares created on a backend, which is # capacity of all the shares created on a backend, which is

View File

@ -813,7 +813,7 @@ class ShareDriver(object):
total_capacity_gb='unknown', total_capacity_gb='unknown',
free_capacity_gb='unknown', free_capacity_gb='unknown',
reserved_percentage=0, reserved_percentage=0,
QoS_support=False, qos=False,
pools=self.pools or None, pools=self.pools or None,
snapshot_support=self.snapshots_are_supported, snapshot_support=self.snapshots_are_supported,
) )

View File

@ -525,7 +525,7 @@ class VNXStorageConnection(driver.StorageConnection):
pool_name=pool['name'], pool_name=pool['name'],
total_capacity_gb=total_size, total_capacity_gb=total_size,
free_capacity_gb=total_size - used_size, free_capacity_gb=total_size - used_size,
QoS_support=False, qos=False,
reserved_percentage=self.reserved_percentage, reserved_percentage=self.reserved_percentage,
) )
stats_dict['pools'].append(pool_stat) stats_dict['pools'].append(pool_stat)

View File

@ -351,7 +351,7 @@ class HDSHNASDriver(driver.ShareDriver):
'total_capacity_gb': total_space, 'total_capacity_gb': total_space,
'free_capacity_gb': free_space, 'free_capacity_gb': free_space,
'reserved_percentage': reserved, 'reserved_percentage': reserved,
'QoS_support': False, 'qos': False,
} }
LOG.info(_LI("HNAS Capabilities: %(data)s."), LOG.info(_LI("HNAS Capabilities: %(data)s."),

View File

@ -422,7 +422,7 @@ class HPE3ParShareDriver(driver.ShareDriver):
'provisioned_capacity_gb': 0, 'provisioned_capacity_gb': 0,
'reserved_percentage': reserved_share_percentage, 'reserved_percentage': reserved_share_percentage,
'max_over_subscription_ratio': max_over_subscription_ratio, 'max_over_subscription_ratio': max_over_subscription_ratio,
'QoS_support': False, 'qos': False,
'thin_provisioning': True, # 3PAR default is thin 'thin_provisioning': True, # 3PAR default is thin
} }

View File

@ -252,7 +252,7 @@ class V3StorageConnection(driver.HuaweiBase):
self.configuration.safe_get( self.configuration.safe_get(
'max_over_subscription_ratio')), 'max_over_subscription_ratio')),
allocated_capacity_gb=capacity['CONSUMEDCAPACITY'], allocated_capacity_gb=capacity['CONSUMEDCAPACITY'],
QoS_support=False, qos=False,
reserved_percentage=0, reserved_percentage=0,
thin_provisioning=[True, False], thin_provisioning=[True, False],
dedupe=[True, False], dedupe=[True, False],

View File

@ -260,7 +260,7 @@ class NetAppCmodeFileStorageLibrary(object):
'total_capacity_gb': total_capacity_gb, 'total_capacity_gb': total_capacity_gb,
'free_capacity_gb': free_capacity_gb, 'free_capacity_gb': free_capacity_gb,
'allocated_capacity_gb': allocated_capacity_gb, 'allocated_capacity_gb': allocated_capacity_gb,
'QoS_support': 'False', 'qos': 'False',
'reserved_percentage': 0, 'reserved_percentage': 0,
'dedupe': [True, False], 'dedupe': [True, False],
'compression': [True, False], 'compression': [True, False],

View File

@ -36,7 +36,7 @@ FAKE_POOLS = [
'reserved_percentage': 0, 'reserved_percentage': 0,
'driver_version': '1.0.0', 'driver_version': '1.0.0',
'storage_protocol': 'iSCSI', 'storage_protocol': 'iSCSI',
'QoS_support': 'False', 'qos': 'False',
}, },
}, },
{ {
@ -52,7 +52,7 @@ FAKE_POOLS = [
'reserved_percentage': 0, 'reserved_percentage': 0,
'driver_version': '1.0.1', 'driver_version': '1.0.1',
'storage_protocol': 'iSER', 'storage_protocol': 'iSER',
'QoS_support': 'True', 'qos': 'True',
}, },
}, },
] ]
@ -161,7 +161,7 @@ class SchedulerStatsControllerTestCase(test.TestCase):
'reserved_percentage': 0, 'reserved_percentage': 0,
'driver_version': '1.0.0', 'driver_version': '1.0.0',
'storage_protocol': 'iSCSI', 'storage_protocol': 'iSCSI',
'QoS_support': 'False', 'qos': 'False',
}, },
}, },
{ {
@ -177,7 +177,7 @@ class SchedulerStatsControllerTestCase(test.TestCase):
'reserved_percentage': 0, 'reserved_percentage': 0,
'driver_version': '1.0.1', 'driver_version': '1.0.1',
'storage_protocol': 'iSER', 'storage_protocol': 'iSER',
'QoS_support': 'True', 'qos': 'True',
}, },
}, },
], ],

View File

@ -27,7 +27,7 @@ POOL1 = {
'capabilities': { 'capabilities': {
'pool_name': 'pool1', 'pool_name': 'pool1',
'driver_handles_share_servers': False, 'driver_handles_share_servers': False,
'QoS_support': 'False', 'qos': 'False',
'timestamp': '2015-03-15T19:15:42.611690', 'timestamp': '2015-03-15T19:15:42.611690',
'allocated_capacity_gb': 5, 'allocated_capacity_gb': 5,
'total_capacity_gb': 10, 'total_capacity_gb': 10,
@ -41,7 +41,7 @@ POOL2 = {
'capabilities': { 'capabilities': {
'pool_name': 'pool2', 'pool_name': 'pool2',
'driver_handles_share_servers': False, 'driver_handles_share_servers': False,
'QoS_support': 'False', 'qos': 'False',
'timestamp': '2015-03-15T19:15:42.611690', 'timestamp': '2015-03-15T19:15:42.611690',
'allocated_capacity_gb': 15, 'allocated_capacity_gb': 15,
'total_capacity_gb': 20, 'total_capacity_gb': 20,
@ -59,7 +59,7 @@ POOLS_DETAIL_VIEW = {
'capabilities': { 'capabilities': {
'pool_name': 'pool1', 'pool_name': 'pool1',
'driver_handles_share_servers': False, 'driver_handles_share_servers': False,
'QoS_support': 'False', 'qos': 'False',
'timestamp': '2015-03-15T19:15:42.611690', 'timestamp': '2015-03-15T19:15:42.611690',
'allocated_capacity_gb': 5, 'allocated_capacity_gb': 5,
'total_capacity_gb': 10, 'total_capacity_gb': 10,
@ -72,7 +72,7 @@ POOLS_DETAIL_VIEW = {
'capabilities': { 'capabilities': {
'pool_name': 'pool2', 'pool_name': 'pool2',
'driver_handles_share_servers': False, 'driver_handles_share_servers': False,
'QoS_support': 'False', 'qos': 'False',
'timestamp': '2015-03-15T19:15:42.611690', 'timestamp': '2015-03-15T19:15:42.611690',
'allocated_capacity_gb': 15, 'allocated_capacity_gb': 15,
'total_capacity_gb': 20, 'total_capacity_gb': 20,

View File

@ -589,7 +589,7 @@ class HostStateTestCase(test.TestCase):
'total_capacity_gb': 500, 'total_capacity_gb': 500,
'free_capacity_gb': 230, 'free_capacity_gb': 230,
'allocated_capacity_gb': 270, 'allocated_capacity_gb': 270,
'QoS_support': 'False', 'qos': 'False',
'reserved_percentage': 0, 'reserved_percentage': 0,
'dying_disks': 100, 'dying_disks': 100,
'super_hero_1': 'spider-man', 'super_hero_1': 'spider-man',
@ -600,7 +600,7 @@ class HostStateTestCase(test.TestCase):
'total_capacity_gb': 1024, 'total_capacity_gb': 1024,
'free_capacity_gb': 1024, 'free_capacity_gb': 1024,
'allocated_capacity_gb': 0, 'allocated_capacity_gb': 0,
'QoS_support': 'False', 'qos': 'False',
'reserved_percentage': 0, 'reserved_percentage': 0,
'dying_disks': 200, 'dying_disks': 200,
'super_hero_1': 'superman', 'super_hero_1': 'superman',
@ -638,7 +638,7 @@ class HostStateTestCase(test.TestCase):
'total_capacity_gb': 10000, 'total_capacity_gb': 10000,
'free_capacity_gb': 10000, 'free_capacity_gb': 10000,
'allocated_capacity_gb': 0, 'allocated_capacity_gb': 0,
'QoS_support': 'False', 'qos': 'False',
'reserved_percentage': 0, 'reserved_percentage': 0,
}, },
], ],

View File

@ -121,7 +121,7 @@ class EMCShareFrameworkTestCase(test.TestCase):
data['total_capacity_gb'] = 'unknown' data['total_capacity_gb'] = 'unknown'
data['free_capacity_gb'] = 'unknown' data['free_capacity_gb'] = 'unknown'
data['reserved_percentage'] = 0 data['reserved_percentage'] = 0
data['QoS_support'] = False data['qos'] = False
data['pools'] = None data['pools'] = None
data['snapshot_support'] = True data['snapshot_support'] = True
self.assertEqual(data, self.driver._stats) self.assertEqual(data, self.driver._stats)

View File

@ -405,7 +405,7 @@ class HDFSNativeShareDriverTestCase(test.TestCase):
return_value=(11111.0, 12345.0)) return_value=(11111.0, 12345.0))
result = self._driver.get_share_stats(True) result = self._driver.get_share_stats(True)
expected_keys = [ expected_keys = [
'QoS_support', 'driver_version', 'share_backend_name', 'qos', 'driver_version', 'share_backend_name',
'free_capacity_gb', 'total_capacity_gb', 'free_capacity_gb', 'total_capacity_gb',
'driver_handles_share_servers', 'driver_handles_share_servers',
'reserved_percentage', 'vendor_name', 'storage_protocol', 'reserved_percentage', 'vendor_name', 'storage_protocol',

View File

@ -505,7 +505,7 @@ class HPE3ParDriverTestCase(test.TestCase):
expected_result = { expected_result = {
'driver_handles_share_servers': True, 'driver_handles_share_servers': True,
'QoS_support': False, 'qos': False,
'driver_version': self.driver.VERSION, 'driver_version': self.driver.VERSION,
'free_capacity_gb': 0, 'free_capacity_gb': 0,
'max_over_subscription_ratio': None, 'max_over_subscription_ratio': None,
@ -559,7 +559,7 @@ class HPE3ParDriverTestCase(test.TestCase):
expected_result = { expected_result = {
'driver_handles_share_servers': True, 'driver_handles_share_servers': True,
'QoS_support': False, 'qos': False,
'driver_version': expected_version, 'driver_version': expected_version,
'free_capacity_gb': expected_free, 'free_capacity_gb': expected_free,
'max_over_subscription_ratio': None, 'max_over_subscription_ratio': None,
@ -594,7 +594,7 @@ class HPE3ParDriverTestCase(test.TestCase):
self.mock_mediator.get_fpg_status.return_value = {'not_called': 1} self.mock_mediator.get_fpg_status.return_value = {'not_called': 1}
expected_result = { expected_result = {
'QoS_support': False, 'qos': False,
'driver_handles_share_servers': True, 'driver_handles_share_servers': True,
'driver_version': expected_version, 'driver_version': expected_version,
'free_capacity_gb': 0, 'free_capacity_gb': 0,

View File

@ -1404,7 +1404,7 @@ class HuaweiShareDriverTestCase(test.TestCase):
expected['reserved_percentage'] = 0 expected['reserved_percentage'] = 0
expected['total_capacity_gb'] = 0.0 expected['total_capacity_gb'] = 0.0
expected['free_capacity_gb'] = 0.0 expected['free_capacity_gb'] = 0.0
expected['QoS_support'] = False expected['qos'] = False
expected["snapshot_support"] = False expected["snapshot_support"] = False
expected["pools"] = [] expected["pools"] = []
pool = dict( pool = dict(
@ -1412,7 +1412,7 @@ class HuaweiShareDriverTestCase(test.TestCase):
total_capacity_gb=2.0, total_capacity_gb=2.0,
free_capacity_gb=1.0, free_capacity_gb=1.0,
allocated_capacity_gb=1.0, allocated_capacity_gb=1.0,
QoS_support=False, qos=False,
reserved_percentage=0, reserved_percentage=0,
compression=[True, False], compression=[True, False],
dedupe=[True, False], dedupe=[True, False],

View File

@ -166,7 +166,7 @@ class GPFSShareDriverTestCase(test.TestCase):
mock.Mock(return_value=(11111.0, 12345.0))) mock.Mock(return_value=(11111.0, 12345.0)))
result = self._driver.get_share_stats(True) result = self._driver.get_share_stats(True)
expected_keys = [ expected_keys = [
'QoS_support', 'driver_version', 'share_backend_name', 'qos', 'driver_version', 'share_backend_name',
'free_capacity_gb', 'total_capacity_gb', 'free_capacity_gb', 'total_capacity_gb',
'driver_handles_share_servers', 'driver_handles_share_servers',
'reserved_percentage', 'vendor_name', 'storage_protocol', 'reserved_percentage', 'vendor_name', 'storage_protocol',

View File

@ -437,7 +437,7 @@ POOLS = [
'total_capacity_gb': 3.3, 'total_capacity_gb': 3.3,
'free_capacity_gb': 1.1, 'free_capacity_gb': 1.1,
'allocated_capacity_gb': 2.2, 'allocated_capacity_gb': 2.2,
'QoS_support': 'False', 'qos': 'False',
'reserved_percentage': 0, 'reserved_percentage': 0,
'dedupe': [True, False], 'dedupe': [True, False],
'compression': [True, False], 'compression': [True, False],
@ -449,7 +449,7 @@ POOLS = [
'total_capacity_gb': 6.0, 'total_capacity_gb': 6.0,
'free_capacity_gb': 2.0, 'free_capacity_gb': 2.0,
'allocated_capacity_gb': 4.0, 'allocated_capacity_gb': 4.0,
'QoS_support': 'False', 'qos': 'False',
'reserved_percentage': 0, 'reserved_percentage': 0,
'dedupe': [True, False], 'dedupe': [True, False],
'compression': [True, False], 'compression': [True, False],
@ -464,7 +464,7 @@ POOLS_VSERVER_CREDS = [
'total_capacity_gb': 'unknown', 'total_capacity_gb': 'unknown',
'free_capacity_gb': 1.1, 'free_capacity_gb': 1.1,
'allocated_capacity_gb': 0.0, 'allocated_capacity_gb': 0.0,
'QoS_support': 'False', 'qos': 'False',
'reserved_percentage': 0, 'reserved_percentage': 0,
'dedupe': [True, False], 'dedupe': [True, False],
'compression': [True, False], 'compression': [True, False],
@ -476,7 +476,7 @@ POOLS_VSERVER_CREDS = [
'total_capacity_gb': 'unknown', 'total_capacity_gb': 'unknown',
'free_capacity_gb': 2.0, 'free_capacity_gb': 2.0,
'allocated_capacity_gb': 0.0, 'allocated_capacity_gb': 0.0,
'QoS_support': 'False', 'qos': 'False',
'reserved_percentage': 0, 'reserved_percentage': 0,
'dedupe': [True, False], 'dedupe': [True, False],
'compression': [True, False], 'compression': [True, False],

View File

@ -1356,7 +1356,7 @@ class GenericShareDriverTestCase(test.TestCase):
fake_stats = {'fake_key': 'fake_value'} fake_stats = {'fake_key': 'fake_value'}
self._driver._stats = fake_stats self._driver._stats = fake_stats
expected_keys = [ expected_keys = [
'QoS_support', 'driver_version', 'share_backend_name', 'qos', 'driver_version', 'share_backend_name',
'free_capacity_gb', 'total_capacity_gb', 'free_capacity_gb', 'total_capacity_gb',
'driver_handles_share_servers', 'driver_handles_share_servers',
'reserved_percentage', 'vendor_name', 'storage_protocol', 'reserved_percentage', 'vendor_name', 'storage_protocol',

View File

@ -408,7 +408,7 @@ class GlusterfsNativeShareDriverTestCase(test.TestCase):
'driver_version': '1.1', 'driver_version': '1.1',
'storage_protocol': 'glusterfs', 'storage_protocol': 'glusterfs',
'reserved_percentage': 0, 'reserved_percentage': 0,
'QoS_support': False, 'qos': False,
'total_capacity_gb': 'unknown', 'total_capacity_gb': 'unknown',
'free_capacity_gb': 'unknown', 'free_capacity_gb': 'unknown',
'pools': None, 'pools': None,

View File

@ -121,7 +121,7 @@ class ShareDriverTestCase(test.TestCase):
def test_get_share_stats_refresh_true(self): def test_get_share_stats_refresh_true(self):
conf = configuration.Configuration(None) conf = configuration.Configuration(None)
expected_keys = [ expected_keys = [
'QoS_support', 'driver_version', 'share_backend_name', 'qos', 'driver_version', 'share_backend_name',
'free_capacity_gb', 'total_capacity_gb', 'free_capacity_gb', 'total_capacity_gb',
'driver_handles_share_servers', 'driver_handles_share_servers',
'reserved_percentage', 'vendor_name', 'storage_protocol', 'reserved_percentage', 'vendor_name', 'storage_protocol',