Merge "Make scheduler check online_extend_support capability"

This commit is contained in:
Zuul 2018-07-13 02:20:26 +00:00 committed by Gerrit Code Review
commit aa50408cbc
6 changed files with 71 additions and 3 deletions

View File

@ -132,6 +132,9 @@ class VolumeDriverCore(base.CinderInterface):
* sparse_copy_volume (Boolean)
Whether copies performed by the volume manager for operations such
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
dict for each pool being used with the backend.
@ -255,6 +258,9 @@ class VolumeDriverCore(base.CinderInterface):
:param volume: The volume to extend.
: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):

View File

@ -15,6 +15,7 @@
from oslo_log import log as logging
from cinder.objects.fields import VolumeAttachStatus
from cinder.scheduler import filters
from cinder.scheduler.filters import extra_specs_ops
@ -24,13 +25,27 @@ LOG = logging.getLogger(__name__)
class CapabilitiesFilter(filters.BaseBackendFilter):
"""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 that the capabilities provided by the services satisfy
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:
return True
@ -80,9 +95,8 @@ class CapabilitiesFilter(filters.BaseBackendFilter):
# Note(zhiteng) Currently only Cinder and Nova are using
# this filter, so the resource type is either instance or
# volume.
resource_type = filter_properties.get('resource_type')
if not self._satisfies_extra_specs(backend_state.capabilities,
resource_type):
filter_properties):
LOG.debug("%(backend_state)s fails resource_type extra_specs "
"requirements", {'backend_state': backend_state})
return False

View File

@ -39,6 +39,7 @@ SERVICE_STATES = {
'volume_backend_name': 'lvm1',
'timestamp': UTC_NOW,
'multiattach': True,
'online_extend_support': True,
'uuid': 'a3a593da-7f8d-4bb7-8b4c-f2bc1e0b4824'},
'host2': {'total_capacity_gb': 2048,
'free_capacity_gb': 300,
@ -50,6 +51,7 @@ SERVICE_STATES = {
'reserved_percentage': 10,
'volume_backend_name': 'lvm2',
'timestamp': UTC_NOW,
'online_extend_support': False,
'uuid': '4200b32b-0bf9-436c-86b2-0675f6ac218e'},
'host3': {'total_capacity_gb': 512,
'free_capacity_gb': 256,

View File

@ -426,6 +426,42 @@ class FilterSchedulerTestCase(test_scheduler.SchedulerTestCase):
ctx, 'host1#lvm1', request_spec, {})
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')
def test_retype_policy_never_migrate_pass(self, _mock_service_get_topic):
# Retype should pass if current host passes filters and

View File

@ -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
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
-------------------

View File

@ -0,0 +1,5 @@
---
fixes:
- |
Make Cinder scheduler check if backend reports `online_extend_support`
before performing an online extend operation.