From 46e1190e6b5c2a1910c2375a8be41c28330950ae Mon Sep 17 00:00:00 2001 From: Gorka Eguileor Date: Mon, 3 Jul 2017 12:22:56 +0200 Subject: [PATCH] Fix scheduler_host_manager limitation We support customization of scheduler's host manager, driver, and filters, but when we made the scheduler Pool aware we greatly limited this possibility because now instead of passing BackendState (previously called HostState) to the filters we are passing PoolState, which cannot be easily customized. Prior to this if you wanted to have a custom BackendState class you would just have to extend HostManager class and define the class attribute backend_state_cls before using it in config's scheduler_host_manager. Now it will not be enough with that because PoolState class is hardcoded in the BackendState's methods, so you'll have to actually copy all the code from that class just so you can replace the PoolState class instantiations. This patch fixes this by creating an instance attribute on initialization method, this way extending classes will just have to call parent's initialization and then replace the value of the pool_state_cls attribute. Due to a circular dependency between BackendState and PoolState (which inherits from BackendState) we cannot just add it as a class attribute, so we do it as an instance attribute instead. If we want to add it as a class attribute we would have to add after the PoolState class definition the following: BackendState.pool_state_cls = PoolState Conceptually that's closer to what we want (a class attribute) but the implementation is worse because you end up assigning the class attribute 270 lines away from where it should have been defined. TrivialFix Change-Id: I2c63806c4e9b1305742c7f07f47b95ba243c1666 --- cinder/scheduler/host_manager.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/cinder/scheduler/host_manager.py b/cinder/scheduler/host_manager.py index 641691676b1..f61eb61fc26 100644 --- a/cinder/scheduler/host_manager.py +++ b/cinder/scheduler/host_manager.py @@ -93,6 +93,12 @@ class BackendState(object): """Mutable and immutable information tracked for a volume backend.""" def __init__(self, host, cluster_name, capabilities=None, service=None): + # NOTE(geguileo): We have a circular dependency between BackendState + # and PoolState and we resolve it with an instance attribute instead + # of a class attribute that we would assign after the PoolState + # declaration because this way we avoid splitting the code. + self.pool_state_cls = PoolState + self.capabilities = None self.service = None self.host = host @@ -221,8 +227,10 @@ class BackendState(object): cur_pool = self.pools.get(pool_name, None) if not cur_pool: # Add new pool - cur_pool = PoolState(self.host, self.cluster_name, - pool_cap, pool_name) + cur_pool = self.pool_state_cls(self.host, + self.cluster_name, + pool_cap, + pool_name) self.pools[pool_name] = cur_pool cur_pool.update_from_volume_capability(pool_cap, service) @@ -239,8 +247,8 @@ class BackendState(object): if len(self.pools) == 0: # No pool was there - single_pool = PoolState(self.host, self.cluster_name, - capability, pool_name) + single_pool = self.pool_state_cls(self.host, self.cluster_name, + capability, pool_name) self._append_backend_info(capability) self.pools[pool_name] = single_pool else: @@ -248,8 +256,10 @@ class BackendState(object): try: single_pool = self.pools[pool_name] except KeyError: - single_pool = PoolState(self.host, self.cluster_name, - capability, pool_name) + single_pool = self.pool_state_cls(self.host, + self.cluster_name, + capability, + pool_name) self._append_backend_info(capability) self.pools[pool_name] = single_pool