Merge "CG creation should be scheduled on backend level"
This commit is contained in:
commit
6a942ba647
@ -397,7 +397,10 @@ class FilterScheduler(driver.Scheduler):
|
||||
new_weighed_hosts = []
|
||||
for host1 in 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)
|
||||
weighed_hosts = new_weighed_hosts
|
||||
if not weighed_hosts:
|
||||
@ -410,6 +413,16 @@ class FilterScheduler(driver.Scheduler):
|
||||
def _schedule(self, context, request_spec, filter_properties=None):
|
||||
weighed_hosts = self._get_weighted_candidates(context, request_spec,
|
||||
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:
|
||||
LOG.warning(_LW('No weighed hosts found for volume '
|
||||
'with properties: %s'),
|
||||
|
@ -192,6 +192,37 @@ class FilterSchedulerTestCase(test_scheduler.SchedulerTestCase):
|
||||
self.assertIsNotNone(weighed_host.obj)
|
||||
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):
|
||||
self.flags(scheduler_max_attempts=4)
|
||||
|
||||
|
@ -50,14 +50,16 @@ class CreateVolumeFlowTestCase(test.TestCase):
|
||||
# called to avoid div by zero errors.
|
||||
self.counter = float(0)
|
||||
|
||||
@mock.patch('cinder.volume.utils.extract_host')
|
||||
@mock.patch('time.time', side_effect=time_inc)
|
||||
@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 = {}
|
||||
consistencygroup_obj = \
|
||||
fake_consistencygroup.fake_consistencyobject_obj(
|
||||
self.ctxt, consistencygroup_id=1, host=None)
|
||||
consistencygroup_get_by_id.return_value = consistencygroup_obj
|
||||
cg_obj = (fake_consistencygroup.
|
||||
fake_consistencyobject_obj(self.ctxt, consistencygroup_id=1,
|
||||
host='host@backend#pool'))
|
||||
consistencygroup_get_by_id.return_value = cg_obj
|
||||
spec = {'volume_id': None,
|
||||
'source_volid': None,
|
||||
'snapshot_id': None,
|
||||
@ -90,6 +92,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
|
||||
|
||||
task._cast_create_volume(self.ctxt, spec, props)
|
||||
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.flows.api.create_volume.'
|
||||
|
@ -27,6 +27,7 @@ from cinder import policy
|
||||
from cinder import quota
|
||||
from cinder import utils
|
||||
from cinder.volume.flows import common
|
||||
from cinder.volume import utils as vol_utils
|
||||
from cinder.volume import volume_types
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -697,8 +698,14 @@ class VolumeCastTask(flow_utils.CinderTask):
|
||||
cgsnapshot_id = request_spec['cgsnapshot_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)
|
||||
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:
|
||||
# NOTE(Rongze Zhu): A simple solution for bug 1008866.
|
||||
#
|
||||
|
Loading…
Reference in New Issue
Block a user