Merge "Make scheduler check online_extend_support capability"
This commit is contained in:
commit
aa50408cbc
@ -132,6 +132,9 @@ class VolumeDriverCore(base.CinderInterface):
|
|||||||
* sparse_copy_volume (Boolean)
|
* sparse_copy_volume (Boolean)
|
||||||
Whether copies performed by the volume manager for operations such
|
Whether copies performed by the volume manager for operations such
|
||||||
as migration should attempt to preserve sparseness.
|
as migration should attempt to preserve sparseness.
|
||||||
|
* online_extend_support (Boolean)
|
||||||
|
Whether the backend supports in-use volume extend or not. Defaults
|
||||||
|
to True.
|
||||||
|
|
||||||
The returned dict may also contain a list, "pools", which has a similar
|
The returned dict may also contain a list, "pools", which has a similar
|
||||||
dict for each pool being used with the backend.
|
dict for each pool being used with the backend.
|
||||||
@ -255,6 +258,9 @@ class VolumeDriverCore(base.CinderInterface):
|
|||||||
|
|
||||||
:param volume: The volume to extend.
|
:param volume: The volume to extend.
|
||||||
:param new_size: The new desired size of the volume.
|
:param new_size: The new desired size of the volume.
|
||||||
|
|
||||||
|
Note that if the volume backend doesn't support extending an in-use
|
||||||
|
volume, the driver should report online_extend_support=False.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def create_snapshot(self, snapshot):
|
def create_snapshot(self, snapshot):
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
from cinder.objects.fields import VolumeAttachStatus
|
||||||
from cinder.scheduler import filters
|
from cinder.scheduler import filters
|
||||||
from cinder.scheduler.filters import extra_specs_ops
|
from cinder.scheduler.filters import extra_specs_ops
|
||||||
|
|
||||||
@ -24,13 +25,27 @@ LOG = logging.getLogger(__name__)
|
|||||||
class CapabilitiesFilter(filters.BaseBackendFilter):
|
class CapabilitiesFilter(filters.BaseBackendFilter):
|
||||||
"""BackendFilter to work with resource (instance & volume) type records."""
|
"""BackendFilter to work with resource (instance & volume) type records."""
|
||||||
|
|
||||||
def _satisfies_extra_specs(self, capabilities, resource_type):
|
def _satisfies_extra_specs(self, capabilities, filter_properties):
|
||||||
"""Check if capabilities satisfy resource type requirements.
|
"""Check if capabilities satisfy resource type requirements.
|
||||||
|
|
||||||
Check that the capabilities provided by the services satisfy
|
Check that the capabilities provided by the services satisfy
|
||||||
the extra specs associated with the resource type.
|
the extra specs associated with the resource type.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
req_spec = filter_properties.get('request_spec')
|
||||||
|
if req_spec and req_spec.get('operation') == 'extend_volume':
|
||||||
|
# NOTE(erlon): By default, cinder considers that every backend
|
||||||
|
# supports volume online extending. Those backends that don't
|
||||||
|
# support it should report online_extend_support=False.
|
||||||
|
online_extends = capabilities.get('online_extend_support', True)
|
||||||
|
if online_extends is False:
|
||||||
|
vol_prop = req_spec.get('volume_properties')
|
||||||
|
attach_status = vol_prop.get('attach_status')
|
||||||
|
if attach_status != VolumeAttachStatus.DETACHED:
|
||||||
|
LOG.debug("Backend doesn't support attached volume extend")
|
||||||
|
return False
|
||||||
|
|
||||||
|
resource_type = filter_properties.get('resource_type')
|
||||||
if not resource_type:
|
if not resource_type:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -80,9 +95,8 @@ class CapabilitiesFilter(filters.BaseBackendFilter):
|
|||||||
# Note(zhiteng) Currently only Cinder and Nova are using
|
# Note(zhiteng) Currently only Cinder and Nova are using
|
||||||
# this filter, so the resource type is either instance or
|
# this filter, so the resource type is either instance or
|
||||||
# volume.
|
# volume.
|
||||||
resource_type = filter_properties.get('resource_type')
|
|
||||||
if not self._satisfies_extra_specs(backend_state.capabilities,
|
if not self._satisfies_extra_specs(backend_state.capabilities,
|
||||||
resource_type):
|
filter_properties):
|
||||||
LOG.debug("%(backend_state)s fails resource_type extra_specs "
|
LOG.debug("%(backend_state)s fails resource_type extra_specs "
|
||||||
"requirements", {'backend_state': backend_state})
|
"requirements", {'backend_state': backend_state})
|
||||||
return False
|
return False
|
||||||
|
@ -39,6 +39,7 @@ SERVICE_STATES = {
|
|||||||
'volume_backend_name': 'lvm1',
|
'volume_backend_name': 'lvm1',
|
||||||
'timestamp': UTC_NOW,
|
'timestamp': UTC_NOW,
|
||||||
'multiattach': True,
|
'multiattach': True,
|
||||||
|
'online_extend_support': True,
|
||||||
'uuid': 'a3a593da-7f8d-4bb7-8b4c-f2bc1e0b4824'},
|
'uuid': 'a3a593da-7f8d-4bb7-8b4c-f2bc1e0b4824'},
|
||||||
'host2': {'total_capacity_gb': 2048,
|
'host2': {'total_capacity_gb': 2048,
|
||||||
'free_capacity_gb': 300,
|
'free_capacity_gb': 300,
|
||||||
@ -50,6 +51,7 @@ SERVICE_STATES = {
|
|||||||
'reserved_percentage': 10,
|
'reserved_percentage': 10,
|
||||||
'volume_backend_name': 'lvm2',
|
'volume_backend_name': 'lvm2',
|
||||||
'timestamp': UTC_NOW,
|
'timestamp': UTC_NOW,
|
||||||
|
'online_extend_support': False,
|
||||||
'uuid': '4200b32b-0bf9-436c-86b2-0675f6ac218e'},
|
'uuid': '4200b32b-0bf9-436c-86b2-0675f6ac218e'},
|
||||||
'host3': {'total_capacity_gb': 512,
|
'host3': {'total_capacity_gb': 512,
|
||||||
'free_capacity_gb': 256,
|
'free_capacity_gb': 256,
|
||||||
|
@ -426,6 +426,42 @@ class FilterSchedulerTestCase(test_scheduler.SchedulerTestCase):
|
|||||||
ctx, 'host1#lvm1', request_spec, {})
|
ctx, 'host1#lvm1', request_spec, {})
|
||||||
self.assertTrue(_mock_service_get_topic.called)
|
self.assertTrue(_mock_service_get_topic.called)
|
||||||
|
|
||||||
|
@mock.patch('cinder.db.service_get_all')
|
||||||
|
def test_backend_passes_filters_online_extend_support_happy_day(
|
||||||
|
self, _mock_service_get_topic):
|
||||||
|
"""Do a successful online extend with backend_passes_filters()."""
|
||||||
|
sched, ctx = self._backend_passes_filters_setup(
|
||||||
|
_mock_service_get_topic)
|
||||||
|
request_spec = {'volume_id': fake.VOLUME_ID,
|
||||||
|
'volume_type': {'name': 'LVM_iSCSI'},
|
||||||
|
'volume_properties': {'project_id': 1,
|
||||||
|
'size': 1,
|
||||||
|
'attach_status': 'attached'},
|
||||||
|
'operation': 'extend_volume'}
|
||||||
|
request_spec = objects.RequestSpec.from_primitives(request_spec)
|
||||||
|
# host1#lvm1 has online_extend_support = True
|
||||||
|
sched.backend_passes_filters(ctx, 'host1#lvm1', request_spec, {})
|
||||||
|
self.assertTrue(_mock_service_get_topic.called)
|
||||||
|
|
||||||
|
@mock.patch('cinder.db.service_get_all')
|
||||||
|
def test_backend_passes_filters_no_online_extend_support(
|
||||||
|
self, _mock_service_get_topic):
|
||||||
|
"""Fail the host due to lack of online extend support."""
|
||||||
|
sched, ctx = self._backend_passes_filters_setup(
|
||||||
|
_mock_service_get_topic)
|
||||||
|
request_spec = {'volume_id': fake.VOLUME_ID,
|
||||||
|
'volume_type': {'name': 'LVM_iSCSI'},
|
||||||
|
'volume_properties': {'project_id': 1,
|
||||||
|
'size': 1,
|
||||||
|
'attach_status': 'attached'},
|
||||||
|
'operation': 'extend_volume'}
|
||||||
|
request_spec = objects.RequestSpec.from_primitives(request_spec)
|
||||||
|
# host2#lvm2 has online_extend_support = False
|
||||||
|
self.assertRaises(exception.NoValidBackend,
|
||||||
|
sched.backend_passes_filters,
|
||||||
|
ctx, 'host2#lvm2', request_spec, {})
|
||||||
|
self.assertTrue(_mock_service_get_topic.called)
|
||||||
|
|
||||||
@mock.patch('cinder.db.service_get_all')
|
@mock.patch('cinder.db.service_get_all')
|
||||||
def test_retype_policy_never_migrate_pass(self, _mock_service_get_topic):
|
def test_retype_policy_never_migrate_pass(self, _mock_service_get_topic):
|
||||||
# Retype should pass if current host passes filters and
|
# Retype should pass if current host passes filters and
|
||||||
|
@ -87,6 +87,11 @@ the backend cannot report the value or 'infinite' if the backend has no upper
|
|||||||
limit. But, it is recommended to report real values as the Cinder scheduler
|
limit. But, it is recommended to report real values as the Cinder scheduler
|
||||||
assigns lowest weight to any storage backend reporting 'unknown' or 'infinite'.
|
assigns lowest weight to any storage backend reporting 'unknown' or 'infinite'.
|
||||||
|
|
||||||
|
**NOTE:** By default, Cinder assumes that the driver supports attached volume
|
||||||
|
extending. If it doesn't, it should report 'online_extend_support=False'.
|
||||||
|
Otherwise the scheduler will attempt to perform the operation, and may leave
|
||||||
|
the volume in 'error_extending' state.
|
||||||
|
|
||||||
Feature Enforcement
|
Feature Enforcement
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
5
releasenotes/notes/bug-1765182-bcafd577f4b81eb6.yaml
Normal file
5
releasenotes/notes/bug-1765182-bcafd577f4b81eb6.yaml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Make Cinder scheduler check if backend reports `online_extend_support`
|
||||||
|
before performing an online extend operation.
|
Loading…
Reference in New Issue
Block a user