From: Zhiteng Huang Date: Tue, 31 Dec 2013 07:00:52 +0000 (+0800) Subject: Replace Simple/Chance Scheduler with FilterScheduler X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=289f63934459baccae1e7c547890cc5f4e9f26b3;p=openstack-build%2Fcinder-build.git Replace Simple/Chance Scheduler with FilterScheduler This patch replaces SimpleScheduler and ChanceScheduler with FilterScheduler. Scheduler manager is changed so that when it detects 'scheduler_driver' is set to SimpleScheduler or ChanceScheduler, it changes underlying scheduler driver to FilterScheduler, and then host manager will use a pre-defined combination of filters & weighers to keep scheduler behavior *MOSTLY* the same as its old counterparts. To simulate ChanceScheduler/SimpleScheduler, 'AvailabilityZoneFilter', 'CapacityFilter' and 'CapabilitiesFilter' are chosen to filter out hosts that isn't in the target AZ, doesn't have sufficient capacity and doesn't support needed capabilities. And newly added 'ChanceWeigher' will randomly pick a host from hosts that passes above filters - just like ChanceScheduler does; for SimpleScheduler, 'AllocatedCapacityWeigher' will sort hosts with their 'allocated_capacity' - the one allocates the least is the winner by default. So the two new weigher, 'ChanceWeigher' and 'AllocatedCapacityWeigher' are the key FilterScheduler to act identical when choosing back-ends to serve requests. The 3 filters on the other hand, are essential to make sure this 'new' Simple/Chance Scheduler can support volume types, encryption and QoS. Partially implements bp: deprecate-chance-and-simple-schedulers Change-Id: I0538b9692a23af6457ed463447fea8e564570848 --- diff --git a/cinder/scheduler/host_manager.py b/cinder/scheduler/host_manager.py index cfcbfcfa0..b676f45a6 100644 --- a/cinder/scheduler/host_manager.py +++ b/cinder/scheduler/host_manager.py @@ -48,6 +48,7 @@ host_manager_opts = [ CONF = cfg.CONF CONF.register_opts(host_manager_opts) +CONF.import_opt('scheduler_driver', 'cinder.scheduler.manager') LOG = logging.getLogger(__name__) @@ -171,6 +172,23 @@ class HostManager(object): 'weights') self.weight_classes = self.weight_handler.get_all_classes() + default_filters = ['AvailabilityZoneFilter', + 'CapacityFilter', + 'CapabilitiesFilter'] + chance = 'cinder.scheduler.chance.ChanceScheduler' + simple = 'cinder.scheduler.simple.SimpleScheduler' + if CONF.scheduler_driver == simple: + CONF.set_override('scheduler_default_filters', default_filters) + CONF.set_override('scheduler_default_weighers', + ['AllocatedCapacityWeigher']) + elif CONF.scheduler_driver == chance: + CONF.set_override('scheduler_default_filters', default_filters) + CONF.set_override('scheduler_default_weighers', + ['ChanceWeigher']) + else: + # Do nothing when some other scheduler is configured + pass + def _choose_host_filters(self, filter_cls_names): """Since the caller may specify which filters to use we need to have an authoritative list of what is permissible. This diff --git a/cinder/scheduler/manager.py b/cinder/scheduler/manager.py index 515ef8c13..a64eaebee 100644 --- a/cinder/scheduler/manager.py +++ b/cinder/scheduler/manager.py @@ -55,6 +55,16 @@ class SchedulerManager(manager.Manager): *args, **kwargs): if not scheduler_driver: scheduler_driver = CONF.scheduler_driver + if scheduler_driver in ['cinder.scheduler.chance.ChanceScheduler', + 'cinder.scheduler.simple.SimpleScheduler']: + scheduler_driver = ('cinder.scheduler.filter_scheduler.' + 'FilterScheduler') + LOG.deprecated(_('ChanceScheduler and SimpleScheduler have been ' + 'deprecated due to lack of support for advanced ' + 'features like: volume types, volume encryption,' + ' QoS etc. These two schedulers can be fully ' + 'replaced by FilterScheduler with certain ' + 'combination of filters and weighers.')) self.driver = importutils.import_object(scheduler_driver) super(SchedulerManager, self).__init__(*args, **kwargs) diff --git a/cinder/tests/conf_fixture.py b/cinder/tests/conf_fixture.py index 841ec3791..bc01704a6 100644 --- a/cinder/tests/conf_fixture.py +++ b/cinder/tests/conf_fixture.py @@ -28,6 +28,7 @@ CONF.import_opt('volume_driver', 'cinder.volume.manager') CONF.import_opt('xiv_ds8k_proxy', 'cinder.volume.drivers.xiv_ds8k') CONF.import_opt('backup_driver', 'cinder.backup.manager') CONF.import_opt('fixed_key', 'cinder.keymgr.conf_key_mgr', group='keymgr') +CONF.import_opt('scheduler_driver', 'cinder.scheduler.manager') def_vol_type = 'fake_vol_type' @@ -50,3 +51,5 @@ def set_defaults(conf): 'cinder.tests.test_xiv_ds8k.XIVDS8KFakeProxyDriver') conf.set_default('backup_driver', 'cinder.tests.backup.fake_service') conf.set_default('fixed_key', default='0' * 64, group='keymgr') + conf.set_default('scheduler_driver', + 'cinder.scheduler.filter_scheduler.FilterScheduler') diff --git a/cinder/tests/scheduler/test_scheduler.py b/cinder/tests/scheduler/test_scheduler.py index 0b3ade1fb..4b2e28cd8 100644 --- a/cinder/tests/scheduler/test_scheduler.py +++ b/cinder/tests/scheduler/test_scheduler.py @@ -20,14 +20,19 @@ Tests For Scheduler """ import mock +from oslo.config import cfg from cinder import context from cinder import exception from cinder.scheduler import driver +from cinder.scheduler import filter_scheduler from cinder.scheduler import manager from cinder import test +CONF = cfg.CONF + + class SchedulerManagerTestCase(test.TestCase): """Test case for scheduler manager.""" @@ -119,6 +124,38 @@ class SchedulerManagerTestCase(test.TestCase): _mock_host_passes.assert_called_once_with(self.context, 'host', request_spec, {}) + def test_chance_simple_scheduler_mocked(self): + # Test FilterScheduler is loaded and predefined combination + # of filters and weighers overrides the default value of config option + # scheduler_default_filters and scheduler_default_weighers when + # ChanceScheduler or SimpleScheduler is configured as scheduler_driver. + chance = 'cinder.scheduler.chance.ChanceScheduler' + simple = 'cinder.scheduler.simple.SimpleScheduler' + default_filters = ['AvailabilityZoneFilter', + 'CapacityFilter', + 'CapabilitiesFilter'] + self.flags(scheduler_driver=chance, + scheduler_default_filters=['CapacityFilter'], + scheduler_default_weighers=['CapacityWeigher']) + self.manager = self.manager_cls() + self.assertTrue(isinstance(self.manager.driver, + filter_scheduler.FilterScheduler)) + self.assertEqual(CONF.scheduler_default_filters, + default_filters) + self.assertEqual(CONF.scheduler_default_weighers, + ['ChanceWeigher']) + + self.flags(scheduler_driver=simple, + scheduler_default_filters=['CapacityFilter'], + scheduler_default_weighers=['CapacityWeigher']) + self.manager = self.manager_cls() + self.assertTrue(isinstance(self.manager.driver, + filter_scheduler.FilterScheduler)) + self.assertEqual(CONF.scheduler_default_filters, + default_filters) + self.assertEqual(CONF.scheduler_default_weighers, + ['AllocatedCapacityWeigher']) + class SchedulerTestCase(test.TestCase): """Test case for base scheduler driver class."""