Merge "Add worker-multiplier for reactive charms"
This commit is contained in:
commit
729234dde1
|
@ -24,6 +24,7 @@ import charms.reactive as reactive
|
|||
import charms.reactive.bus
|
||||
import charmhelpers.contrib.hahelpers.cluster as ch_cluster
|
||||
import charmhelpers.contrib.network.ip as ch_ip
|
||||
import charmhelpers.contrib.openstack.context as ch_context
|
||||
import charmhelpers.contrib.openstack.utils as ch_utils
|
||||
import charmhelpers.core.hookenv as hookenv
|
||||
import charmhelpers.core.host as ch_host
|
||||
|
@ -860,6 +861,63 @@ class APIConfigurationAdapter(ConfigurationAdapter):
|
|||
ctxt['memcache_port'])
|
||||
return ctxt
|
||||
|
||||
@property
|
||||
@hookenv.cached
|
||||
def workers(self):
|
||||
"""Return the a number of workers that depends on the
|
||||
config('worker_muliplier') and the number of cpus. This function uses
|
||||
the charmhelpers.contrib.openstack.context.WorkerConfigContext() to do
|
||||
the heavy lifting so that any changes in charmhelpers propagate to this
|
||||
function
|
||||
|
||||
:returns: <int> the number of workers to apply to a configuration file.
|
||||
"""
|
||||
return ch_context.WorkerConfigContext()()["workers"]
|
||||
|
||||
@property
|
||||
@hookenv.cached
|
||||
def wsgi_worker_context(self):
|
||||
"""Return a WSGIWorkerConfigContext dictionary.
|
||||
|
||||
This is used to configure a WSGI worker. The charm_instance class can
|
||||
define some attributes (or properties - anything getattr(...) will work
|
||||
against for:
|
||||
|
||||
wsgi_script: a script/name to pass to the WSGIW... constructor
|
||||
wsgi_admin_script: a script/name to pass to the WSGIW...
|
||||
constructor
|
||||
wsgi_public_script: a script/name to pass to the WSGIW...
|
||||
constructor
|
||||
wsgi_process_weight: an float between 0.0 and 1.0 to split the
|
||||
share of all workers between main, admin and public workers.
|
||||
wsgi_admin_process_weight: an float between 0.0 and 1.0 to split
|
||||
the share of all workers between main, admin and public workers
|
||||
wsgi_public_process_weight: an float between 0.0 and 1.0 to split
|
||||
the share of all workers between main, admin and public workers
|
||||
|
||||
The sum of the process weights should equal 1 to make sense.
|
||||
|
||||
:returns: WSGIWorkerConfigContext dictionary.
|
||||
"""
|
||||
charm_instance = self.charm_instance or {}
|
||||
kwargs = dict(
|
||||
name=getattr(charm_instance, 'name', None),
|
||||
script=getattr(charm_instance, 'wsgi_script', None),
|
||||
admin_script=getattr(charm_instance, 'wsgi_admin_script', None),
|
||||
public_script=getattr(charm_instance, 'wsgi_public_script', None),
|
||||
process_weight=getattr(
|
||||
charm_instance, 'wsgi_process_weight', None),
|
||||
admin_process_weight=getattr(
|
||||
charm_instance, 'wsgi_admin_process_weight', None),
|
||||
public_process_weight=getattr(
|
||||
charm_instance, 'wsgi_public_process_weight', None),
|
||||
)
|
||||
# filtering the kwargs of Nones allows the default arguments on
|
||||
# WSGIWorkerConfigContext.__init__(...) to be used.
|
||||
filtered_kwargs = dict((k, v) for k, v in kwargs.items()
|
||||
if v is not None)
|
||||
return ch_context.WSGIWorkerConfigContext(**filtered_kwargs)()
|
||||
|
||||
|
||||
def make_default_relation_adapter(base_cls, relation, properties):
|
||||
"""Create a default relation adapter using a base class, and custom
|
||||
|
|
|
@ -146,6 +146,18 @@ class OpenStackAPICharm(OpenStackCharm):
|
|||
# If None, then the default ConfigurationAdapter is used.
|
||||
configuration_class = os_adapters.APIConfigurationAdapter
|
||||
|
||||
# These can be overriden in the derived charm class to allow specialism of
|
||||
# config files. These values are read in the APIConfigurationAdapter and
|
||||
# used to furnish the dictionary provided from the property
|
||||
# 'wsgi_worker_context'. e.g. config.wsgi_worker_context.processes would
|
||||
# be the number of processes for the main API wsgi worker.
|
||||
wsgi_script = None
|
||||
wsgi_admin_script = None
|
||||
wsgi_public_script = None
|
||||
wsgi_process_weight = None # use the default from charm-helpers
|
||||
wsgi_admin_process_weight = None # use the default from charm-helpers
|
||||
wsgi_public_process_weight = None # use the default from charm-helpers
|
||||
|
||||
def upgrade_charm(self):
|
||||
"""Setup token cache in case previous charm version did not."""
|
||||
self.setup_token_cache()
|
||||
|
|
|
@ -32,6 +32,8 @@ sys.modules['charmhelpers.contrib.openstack.utils'] = (
|
|||
charmhelpers.contrib.openstack.utils)
|
||||
sys.modules['charmhelpers.contrib.openstack.templating'] = (
|
||||
charmhelpers.contrib.openstack.templating)
|
||||
sys.modules['charmhelpers.contrib.openstack.context'] = (
|
||||
charmhelpers.contrib.openstack.context)
|
||||
sys.modules['charmhelpers.contrib.network'] = charmhelpers.contrib.network
|
||||
sys.modules['charmhelpers.contrib.network.ip'] = (
|
||||
charmhelpers.contrib.network.ip)
|
||||
|
|
|
@ -790,6 +790,87 @@ class TestAPIConfigurationAdapter(unittest.TestCase):
|
|||
memcache.return_value = {'memcache_url': 'hello'}
|
||||
self.assertEquals(c.memcache_url, 'hello')
|
||||
|
||||
def test_workers(self):
|
||||
class FakeWorkerConfigContext(object):
|
||||
def __call__(self):
|
||||
return {"workers": 8}
|
||||
|
||||
with mock.patch.object(adapters.ch_context, 'WorkerConfigContext',
|
||||
new=FakeWorkerConfigContext):
|
||||
c = adapters.APIConfigurationAdapter()
|
||||
self.assertEquals(c.workers, 8)
|
||||
|
||||
def test_wsgi_worker_context(self):
|
||||
class ChInstance1(object):
|
||||
name = 'test-name'
|
||||
wsgi_script = 'test-script'
|
||||
api_ports = {}
|
||||
|
||||
class ChInstance2(object):
|
||||
name = 'test-name'
|
||||
wsgi_script = 'test-script'
|
||||
wsgi_admin_script = 'test-admin-script'
|
||||
wsgi_public_script = 'test-public-script'
|
||||
wsgi_process_weight = 0.5
|
||||
wsgi_admin_process_weight = 0.1
|
||||
wsgi_public_process_weight = 0.4
|
||||
api_ports = {}
|
||||
|
||||
class ChInstance3(object):
|
||||
name = 'test-name'
|
||||
wsgi_script = None
|
||||
wsgi_admin_script = 'test-admin-script'
|
||||
wsgi_public_script = 'test-public-script'
|
||||
wsgi_process_weight = None
|
||||
wsgi_admin_process_weight = 0.1
|
||||
wsgi_public_process_weight = 0.4
|
||||
api_ports = {}
|
||||
|
||||
class FakeWSGIWorkerConfigContext():
|
||||
copy_kwargs = None
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.__class__.copy_kwargs = kwargs.copy()
|
||||
|
||||
def __call__(self):
|
||||
return "T"
|
||||
|
||||
with mock.patch.object(adapters.ch_context, 'WSGIWorkerConfigContext',
|
||||
new=FakeWSGIWorkerConfigContext):
|
||||
# start with no charm instance to get default values
|
||||
c = adapters.APIConfigurationAdapter()
|
||||
self.assertEquals(c.wsgi_worker_context, "T")
|
||||
self.assertEquals(FakeWSGIWorkerConfigContext.copy_kwargs, {})
|
||||
# start with a minimal charm_instance
|
||||
instance = ChInstance1()
|
||||
c = adapters.APIConfigurationAdapter(charm_instance=instance)
|
||||
self.assertEquals(c.wsgi_worker_context, "T")
|
||||
self.assertEquals(FakeWSGIWorkerConfigContext.copy_kwargs,
|
||||
{'name': 'test-name', 'script': 'test-script'})
|
||||
# And then, all the options set:
|
||||
instance = ChInstance2()
|
||||
c = adapters.APIConfigurationAdapter(charm_instance=instance)
|
||||
self.assertEquals(c.wsgi_worker_context, "T")
|
||||
self.assertEquals(FakeWSGIWorkerConfigContext.copy_kwargs,
|
||||
{'name': 'test-name',
|
||||
'script': 'test-script',
|
||||
'admin_script': 'test-admin-script',
|
||||
'public_script': 'test-public-script',
|
||||
'process_weight': 0.5,
|
||||
'admin_process_weight': 0.1,
|
||||
'public_process_weight': 0.4})
|
||||
# and finally, with some of the options set to None, to test
|
||||
# filtering
|
||||
instance = ChInstance3()
|
||||
c = adapters.APIConfigurationAdapter(charm_instance=instance)
|
||||
self.assertEquals(c.wsgi_worker_context, "T")
|
||||
self.assertEquals(FakeWSGIWorkerConfigContext.copy_kwargs,
|
||||
{'name': 'test-name',
|
||||
'admin_script': 'test-admin-script',
|
||||
'public_script': 'test-public-script',
|
||||
'admin_process_weight': 0.1,
|
||||
'public_process_weight': 0.4})
|
||||
|
||||
|
||||
class FakePeerHARelationAdapter(object):
|
||||
|
||||
|
|
Loading…
Reference in New Issue