Deprecate unlimited compute actions

We already deprecated the unlimited max_concurrent_live_migrations
config value and now we do the same for max_concurrent_builds and
max_concurrent_snapshots as well. The reason is similar.
* The unlimited meaning was a lie, it was limited by other constructs in
  the code. For these option the limit was the size of the RPC executor
  defaulted to 64.
* In native threading mode having unlimited concurrent tasks is
  unfeasible due to the memory cost of native threads for each task.

The deprecation is done in a way that in eventlet mode we keep a similar
behavior as before but in native threading mode we enforce a strict
maximum even if unlimited is requested.

Change-Id: Ibbf76c2c85729820035c9791719bf2c864bce12b
Signed-off-by: Balazs Gibizer <gibi@redhat.com>
This commit is contained in:
Balazs Gibizer
2026-02-05 18:11:06 +01:00
parent 00f554fd92
commit efd61188c1
4 changed files with 112 additions and 39 deletions
+68 -31
View File
@@ -672,37 +672,12 @@ class ComputeManager(manager.Manager):
self._syncs_in_progress_lock = threading.Lock()
self.send_instance_updates = (
CONF.filter_scheduler.track_instance_changes)
if CONF.max_concurrent_builds != 0:
self._build_semaphore = threading.Semaphore(
CONF.max_concurrent_builds)
else:
self._build_semaphore = compute_utils.UnlimitedSemaphore()
if CONF.max_concurrent_snapshots > 0:
self._snapshot_semaphore = threading.Semaphore(
CONF.max_concurrent_snapshots)
else:
self._snapshot_semaphore = compute_utils.UnlimitedSemaphore()
if CONF.max_concurrent_live_migrations > 0:
self._live_migration_executor = nova.utils.create_executor(
max_workers=CONF.max_concurrent_live_migrations)
else:
# setting CONF.max_concurrent_live_migrations to 0 (unlimited)
# is deprecated but still supported, so we need to use a sane
# default values for each threading mode
LOG.warning("Nova compute deprecated the support of unlimited "
"parallel live migration so "
"[DEFAULT]max_concurrent_live_migrations configured "
"with value 0 is deprecated and will not be supported "
"in future releases. Please set an explicit positive"
"value to this config option instead.")
if utils.concurrency_mode_threading():
self._live_migration_executor = nova.utils.create_executor(
max_workers=5)
else:
# In eventlet mode we need to keep backward compatibility and
# 1000 greenthreads to emulate unlimited.
self._live_migration_executor = nova.utils.create_executor(
max_workers=1000)
self._build_semaphore = threading.Semaphore(
self._get_max_concurrent_builds())
self._snapshot_semaphore = threading.Semaphore(
self._get_max_concurrent_snapshots())
self._live_migration_executor = nova.utils.create_executor(
max_workers=self._get_max_concurrent_live_migrations())
# This is a dict, keyed by instance uuid, to a two-item tuple of
# migration object and Future for the queued live migration.
@@ -722,6 +697,68 @@ class ComputeManager(manager.Manager):
self.rt = resource_tracker.ResourceTracker(
self.host, self.driver, reportclient=self.reportclient)
def _get_max_concurrent_builds(self):
if CONF.max_concurrent_builds > 0:
return CONF.max_concurrent_builds
# setting CONF.max_concurrent_builds to 0 (unlimited)
# is deprecated but still supported, so we need to use a sane
# default values for each threading mode
LOG.warning("Nova compute deprecated the support of unlimited "
"parallel instance builds so "
"[DEFAULT]max_concurrent_builds configured "
"with value 0 is deprecated and will not be supported "
"in future releases. Please set an explicit positive "
"value to this config option instead.")
if utils.concurrency_mode_threading():
# Fall back to the default of the config
return 10
else:
# In eventlet mode we need to keep backward compatibility, and
# we use 1000 to emulate unlimited
return 1000
def _get_max_concurrent_snapshots(self):
if CONF.max_concurrent_snapshots > 0:
return CONF.max_concurrent_snapshots
# setting CONF.max_concurrent_snapshots to 0 (unlimited)
# is deprecated but still supported, so we need to use a sane
# default values for each threading mode
LOG.warning("Nova compute deprecated the support of unlimited "
"parallel instance snapshots so "
"[DEFAULT]max_concurrent_snapshots configured "
"with value 0 is deprecated and will not be supported "
"in future releases. Please set an explicit positive "
"value to this config option instead.")
if utils.concurrency_mode_threading():
# Fall back to the default of the config
return 5
else:
# In eventlet mode we need to keep backward compatibility, and
# we use 1000 to emulate unlimited
return 1000
def _get_max_concurrent_live_migrations(self):
if CONF.max_concurrent_live_migrations > 0:
return CONF.max_concurrent_live_migrations
# setting CONF.max_concurrent_live_migrations to 0 (unlimited)
# is deprecated but still supported, so we need to use a sane
# default values for each threading mode
LOG.warning("Nova compute deprecated the support of unlimited "
"parallel live migration so "
"[DEFAULT]max_concurrent_live_migrations configured "
"with value 0 is deprecated and will not be supported "
"in future releases. Please set an explicit positive"
"value to this config option instead.")
if utils.concurrency_mode_threading():
return 5
else:
# In eventlet mode we need to keep backward compatibility and
# 1000 greenthreads to emulate unlimited
return 1000
@contextlib.contextmanager
def syncs_in_progress(self) -> Iterator[set[str]]:
with self._syncs_in_progress_lock:
+10 -2
View File
@@ -666,7 +666,11 @@ per compute node.
Possible Values:
* 0 : treated as unlimited.
* ``0``: Deprecated since 33.0.0 (2026.1 Gazpacho). This value was previously
documented as meaning unlimited. Since this release, the implementation keeps
using 1000 as the real limit in eventlet mode and will use 10 in native
threading mode. In the future release when eventlet support is removed, 0 as
a valid value will also be removed.
* Any positive integer representing maximum concurrent builds.
"""),
cfg.IntOpt('max_concurrent_snapshots',
@@ -680,7 +684,11 @@ compute node.
Possible Values:
* 0 : treated as unlimited.
* ``0``: Deprecated since 33.0.0 (2026.1 Gazpacho). This value was previously
documented as meaning unlimited. Since this release, the implementation keeps
using 1000 as the real limit in eventlet mode and will use 5 in native
threading mode. In the future release when eventlet support is removed, 0 as
a valid value will also be removed.
* Any positive integer representing maximum concurrent snapshots.
"""),
cfg.IntOpt('max_concurrent_live_migrations',
+8 -6
View File
@@ -979,9 +979,10 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
def test_max_concurrent_builds_semaphore_unlimited(self):
self.flags(max_concurrent_builds=0)
compute = manager.ComputeManager()
self.assertEqual(0, compute._build_semaphore.balance)
self.assertIsInstance(compute._build_semaphore,
compute_utils.UnlimitedSemaphore)
if utils.concurrency_mode_threading():
self.assertEqual(10, compute._build_semaphore._value)
else:
self.assertEqual(1000, compute._build_semaphore._value)
@mock.patch('nova.objects.Instance.save')
@mock.patch('nova.compute.manager.ComputeManager.'
@@ -1013,9 +1014,10 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
def test_max_concurrent_snapshots_semaphore_unlimited(self):
self.flags(max_concurrent_snapshots=0)
compute = manager.ComputeManager()
self.assertEqual(0, compute._snapshot_semaphore.balance)
self.assertIsInstance(compute._snapshot_semaphore,
compute_utils.UnlimitedSemaphore)
if utils.concurrency_mode_threading():
self.assertEqual(5, compute._snapshot_semaphore._value)
else:
self.assertEqual(1000, compute._snapshot_semaphore._value)
def test_nil_out_inst_obj_host_and_node_sets_nil(self):
instance = fake_instance.fake_instance_obj(self.context,
@@ -18,6 +18,24 @@ upgrade:
higher value explicitly before the upgrade. Please read the
`concurrency <https://docs.openstack.org/nova/latest/admin/concurrency.html>`__
guide for more details.
- |
The meaning of the 0 value of the config option
``[DEFAULT]max_concurrent_builds`` has been changed. In the past
it meant "unlimited" but actually it was limited by the oslo.messaging's
``executor_thread_pool_size`` config option. For eventlet mode "unlimited"
now means 1000 concurrent builds. For the native threading mode it is
now reduced to 10 native threads. Please also read the `concurrency
<https://docs.openstack.org/nova/latest/admin/concurrency.html>`__
guide for more details.
- |
The meaning of the 0 value of the config option
``[DEFAULT]max_concurrent_snapshots`` has been changed. In the past
it meant "unlimited" but actually it was limited by the oslo.messaging's
``executor_thread_pool_size`` config option. For eventlet mode "unlimited"
now means 1000 concurrent snapshots. For the native threading mode it is
now reduced to 5 native threads. Please also read the `concurrency
<https://docs.openstack.org/nova/latest/admin/concurrency.html>`__
guide for more details.
deprecations:
- |
The possible 0 value of the configuration option
@@ -26,3 +44,11 @@ deprecations:
default value, 1, of this config option. If more performant live migration
is needed, use the ``live_migration_parallel_connections`` config option
instead.
- |
The possible 0 value of the configuration option
``[DEFAULT]max_concurrent_builds`` is deprecated and will be
removed in a future release.
- |
The possible 0 value of the configuration option
``[DEFAULT]max_concurrent_snapshots`` is deprecated and will be
removed in a future release.