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
This commit is contained in:
Gorka Eguileor 2017-07-03 12:22:56 +02:00
parent a688b872be
commit 46e1190e6b
1 changed files with 16 additions and 6 deletions

View File

@ -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