Merge "CG creation should be scheduled on backend level"

This commit is contained in:
Jenkins 2015-11-12 04:03:00 +00:00 committed by Gerrit Code Review
commit 6a942ba647
4 changed files with 61 additions and 7 deletions

View File

@ -397,7 +397,10 @@ class FilterScheduler(driver.Scheduler):
new_weighed_hosts = [] new_weighed_hosts = []
for host1 in weighed_hosts: for host1 in weighed_hosts:
for host2 in temp_weighed_hosts: for host2 in temp_weighed_hosts:
if host1.obj.host == host2.obj.host: # Should schedule creation of CG on backend level,
# not pool level.
if (utils.extract_host(host1.obj.host) ==
utils.extract_host(host2.obj.host)):
new_weighed_hosts.append(host1) new_weighed_hosts.append(host1)
weighed_hosts = new_weighed_hosts weighed_hosts = new_weighed_hosts
if not weighed_hosts: if not weighed_hosts:
@ -410,6 +413,16 @@ class FilterScheduler(driver.Scheduler):
def _schedule(self, context, request_spec, filter_properties=None): def _schedule(self, context, request_spec, filter_properties=None):
weighed_hosts = self._get_weighted_candidates(context, request_spec, weighed_hosts = self._get_weighted_candidates(context, request_spec,
filter_properties) filter_properties)
# When we get the weighed_hosts, we clear those hosts whose backend
# is not same as consistencygroup's backend.
CG_backend = request_spec.get('CG_backend')
if weighed_hosts and CG_backend:
# Get host name including host@backend#pool info from
# weighed_hosts.
for host in weighed_hosts[::-1]:
backend = utils.extract_host(host.obj.host)
if backend != CG_backend:
weighed_hosts.remove(host)
if not weighed_hosts: if not weighed_hosts:
LOG.warning(_LW('No weighed hosts found for volume ' LOG.warning(_LW('No weighed hosts found for volume '
'with properties: %s'), 'with properties: %s'),

View File

@ -192,6 +192,37 @@ class FilterSchedulerTestCase(test_scheduler.SchedulerTestCase):
self.assertIsNotNone(weighed_host.obj) self.assertIsNotNone(weighed_host.obj)
self.assertTrue(_mock_service_get_all_by_topic.called) self.assertTrue(_mock_service_get_all_by_topic.called)
@mock.patch('cinder.db.service_get_all_by_topic')
def test_create_volume_clear_host_different_with_cg(self,
_mock_service_get_all):
# Ensure we clear those hosts whose backend is not same as
# consistencygroup's backend.
sched = fakes.FakeFilterScheduler()
sched.host_manager = fakes.FakeHostManager()
fakes.mock_host_manager_db_calls(_mock_service_get_all)
fake_context = context.RequestContext('user', 'project')
request_spec = {'volume_properties': {'project_id': 1,
'size': 1},
'volume_type': {'name': 'LVM_iSCSI'},
'CG_backend': 'host@lvmdriver'}
weighed_host = sched._schedule(fake_context, request_spec, {})
self.assertIsNone(weighed_host)
@mock.patch('cinder.db.service_get_all_by_topic')
def test_create_volume_host_same_as_cg(self, _mock_service_get_all):
# Ensure we don't clear the host whose backend is same as
# consistencygroup's backend.
sched = fakes.FakeFilterScheduler()
sched.host_manager = fakes.FakeHostManager()
fakes.mock_host_manager_db_calls(_mock_service_get_all)
fake_context = context.RequestContext('user', 'project')
request_spec = {'volume_properties': {'project_id': 1,
'size': 1},
'volume_type': {'name': 'LVM_iSCSI'},
'CG_backend': 'host1'}
weighed_host = sched._schedule(fake_context, request_spec, {})
self.assertEqual('host1#lvm1', weighed_host.obj.host)
def test_max_attempts(self): def test_max_attempts(self):
self.flags(scheduler_max_attempts=4) self.flags(scheduler_max_attempts=4)

View File

@ -50,14 +50,16 @@ class CreateVolumeFlowTestCase(test.TestCase):
# called to avoid div by zero errors. # called to avoid div by zero errors.
self.counter = float(0) self.counter = float(0)
@mock.patch('cinder.volume.utils.extract_host')
@mock.patch('time.time', side_effect=time_inc) @mock.patch('time.time', side_effect=time_inc)
@mock.patch('cinder.objects.ConsistencyGroup.get_by_id') @mock.patch('cinder.objects.ConsistencyGroup.get_by_id')
def test_cast_create_volume(self, consistencygroup_get_by_id, mock_time): def test_cast_create_volume(self, consistencygroup_get_by_id, mock_time,
mock_extract_host):
props = {} props = {}
consistencygroup_obj = \ cg_obj = (fake_consistencygroup.
fake_consistencygroup.fake_consistencyobject_obj( fake_consistencyobject_obj(self.ctxt, consistencygroup_id=1,
self.ctxt, consistencygroup_id=1, host=None) host='host@backend#pool'))
consistencygroup_get_by_id.return_value = consistencygroup_obj consistencygroup_get_by_id.return_value = cg_obj
spec = {'volume_id': None, spec = {'volume_id': None,
'source_volid': None, 'source_volid': None,
'snapshot_id': None, 'snapshot_id': None,
@ -90,6 +92,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
task._cast_create_volume(self.ctxt, spec, props) task._cast_create_volume(self.ctxt, spec, props)
consistencygroup_get_by_id.assert_called_once_with(self.ctxt, 5) consistencygroup_get_by_id.assert_called_once_with(self.ctxt, 5)
mock_extract_host.assert_called_once_with('host@backend#pool')
@mock.patch('cinder.volume.volume_types.is_encrypted') @mock.patch('cinder.volume.volume_types.is_encrypted')
@mock.patch('cinder.volume.flows.api.create_volume.' @mock.patch('cinder.volume.flows.api.create_volume.'

View File

@ -27,6 +27,7 @@ from cinder import policy
from cinder import quota from cinder import quota
from cinder import utils from cinder import utils
from cinder.volume.flows import common from cinder.volume.flows import common
from cinder.volume import utils as vol_utils
from cinder.volume import volume_types from cinder.volume import volume_types
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -697,8 +698,14 @@ class VolumeCastTask(flow_utils.CinderTask):
cgsnapshot_id = request_spec['cgsnapshot_id'] cgsnapshot_id = request_spec['cgsnapshot_id']
if cgroup_id: if cgroup_id:
# If cgroup_id existed, we should cast volume to the scheduler
# to choose a proper pool whose backend is same as CG's backend.
cgroup = objects.ConsistencyGroup.get_by_id(context, cgroup_id) cgroup = objects.ConsistencyGroup.get_by_id(context, cgroup_id)
host = cgroup.host # FIXME(wanghao): CG_backend got added before request_spec was
# converted to versioned objects. We should make sure that this
# will be handled by object version translations once we add
# RequestSpec object.
request_spec['CG_backend'] = vol_utils.extract_host(cgroup.host)
elif snapshot_id and CONF.snapshot_same_host: elif snapshot_id and CONF.snapshot_same_host:
# NOTE(Rongze Zhu): A simple solution for bug 1008866. # NOTE(Rongze Zhu): A simple solution for bug 1008866.
# #