Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion cinder/scheduler/filters/capacity_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@

LOG = logging.getLogger(__name__)

_SAME_AGGREGATE_MIGRATION_OPERATIONS = (
'migrate_volume',
'find_backend_for_connector',
)


class CapacityFilter(filters.BaseBackendFilter):
"""Capacity filters based on volume backend's capacity utilization."""
Expand All @@ -45,7 +50,8 @@ def backend_passes(self, backend_state, filter_properties):
source_agg_id = filter_properties.get('source_aggregate_id')
if source_agg_id:
spec = filter_properties.get('request_spec', {})
if spec.get('operation') == 'migrate_volume':
if (spec.get('operation') in
_SAME_AGGREGATE_MIGRATION_OPERATIONS):
dest_agg_id = None
if backend_state.capabilities:
dest_agg_id = backend_state.capabilities.get(
Expand Down
3 changes: 3 additions & 0 deletions cinder/scheduler/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,9 @@ def _retype_volume_set_error(self, context, ex, request_spec,
def find_backend_for_connector(self, context, connector, request_spec,
volume_size, filter_properties=None):
self._wait_for_scheduler()
volume = request_spec.get('volume_properties')
if volume:
self._set_source_aggregate_id(volume, filter_properties)
backend = self.driver.find_backend_for_connector(context,
connector,
request_spec,
Expand Down
28 changes: 26 additions & 2 deletions cinder/tests/unit/scheduler/test_host_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,9 @@ def test_filter_provisioning_type(self, _mock_serv_is_up, volume_type):
'service': service})
self.assertTrue(filt_cls.backend_passes(host, filter_properties))

def test_filter_passes_same_aggregate_migration(self, _mock_serv_is_up):
@ddt.data('migrate_volume', 'find_backend_for_connector')
def test_filter_passes_same_aggregate_migration(
self, operation, _mock_serv_is_up):
"""Cross-vcenter migration with same aggregate_id should pass.

When migrating a volume between vcenters where both pools share the
Expand All @@ -609,7 +611,7 @@ def test_filter_passes_same_aggregate_migration(self, _mock_serv_is_up):
'size': 2048,
'request_spec': {
'volume_id': fake.VOLUME_ID,
'operation': 'migrate_volume',
'operation': operation,
'volume_properties': {
'host': 'vc-a-0@vmware_fcd#pool_A',
},
Expand Down Expand Up @@ -657,6 +659,28 @@ def test_filter_fails_different_aggregate_migration(
'aggregate_id': 'agg_456'}})
self.assertFalse(filt_cls.backend_passes(host, filter_properties))

def test_filter_fails_same_aggregate_non_migration_operation(
self, _mock_serv_is_up):
_mock_serv_is_up.return_value = True
filt_cls = self.class_map['CapacityFilter']()
filter_properties = {
'size': 2048,
'request_spec': {
'volume_id': fake.VOLUME_ID,
'operation': 'create_volume',
},
'source_aggregate_id': 'agg_123',
}
service = {'disabled': False}
host = fakes.FakeBackendState('vc-b-0@vmware_fcd#pool_B',
{'total_capacity_gb': 5000,
'free_capacity_gb': 100,
'updated_at': None,
'service': service,
'capabilities': {
'aggregate_id': 'agg_123'}})
self.assertFalse(filt_cls.backend_passes(host, filter_properties))

def test_filter_passes_migration_no_aggregate_id(self, _mock_serv_is_up):
"""Migration without aggregate_id should use normal capacity checks.

Expand Down
26 changes: 25 additions & 1 deletion cinder/tests/unit/scheduler/test_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -756,7 +756,7 @@ def test_get_az(self):
@mock.patch('cinder.scheduler.driver.Scheduler.find_backend_for_connector')
def test_find_backend_for_connector(self, _mock_find_backend_for_conector):
connector = mock.Mock()
request_spec = mock.Mock()
request_spec = {}
volume_size = mock.Mock()
backend_ret = mock.Mock(host='fake-host',
cluster_name='fake-cluster', capabilities=[])
Expand All @@ -772,6 +772,30 @@ def test_find_backend_for_connector(self, _mock_find_backend_for_conector):
'capabilities': backend_ret.capabilities
})

@mock.patch('cinder.scheduler.driver.Scheduler.find_backend_for_connector')
def test_find_backend_for_connector_sets_source_aggregate_id(
self, _mock_find_backend_for_connector):
volume = fake_volume.fake_volume_obj(
self.context, host='vc-a-0@vmware_fcd#pool_A')
pool_state = mock.Mock(capabilities={'aggregate_id': 'agg_123'})
backend_state = mock.Mock(pools={'pool_A': pool_state})
self.manager.driver.host_manager.backend_state_map = {
'vc-a-0@vmware_fcd': backend_state}
backend = mock.Mock(host='fake-host', cluster_name=None,
capabilities={})
_mock_find_backend_for_connector.return_value = backend
connector = mock.Mock()
request_spec = {'volume_properties': volume}
filter_properties = {}

self.manager.find_backend_for_connector(
self.context, connector, request_spec, 1, filter_properties)

self.assertEqual('agg_123',
filter_properties.get('source_aggregate_id'))
_mock_find_backend_for_connector.assert_called_once_with(
self.context, connector, request_spec, filter_properties)


class SchedulerTestCase(test.TestCase):
"""Test case for base scheduler driver class."""
Expand Down