diff --git a/charmhelpers/contrib/openstack/context.py b/charmhelpers/contrib/openstack/context.py index 6cd91adb..2adf2cb8 100644 --- a/charmhelpers/contrib/openstack/context.py +++ b/charmhelpers/contrib/openstack/context.py @@ -1232,31 +1232,50 @@ MAX_DEFAULT_WORKERS = 4 DEFAULT_MULTIPLIER = 2 +def _calculate_workers(): + ''' + Determine the number of worker processes based on the CPU + count of the unit containing the application. + + Workers will be limited to MAX_DEFAULT_WORKERS in + container environments where no worker-multipler configuration + option been set. + + @returns int: number of worker processes to use + ''' + multiplier = config('worker-multiplier') or DEFAULT_MULTIPLIER + count = int(_num_cpus() * multiplier) + if multiplier > 0 and count == 0: + count = 1 + + if config('worker-multiplier') is None and is_container(): + # NOTE(jamespage): Limit unconfigured worker-multiplier + # to MAX_DEFAULT_WORKERS to avoid insane + # worker configuration in LXD containers + # on large servers + # Reference: https://pad.lv/1665270 + count = min(count, MAX_DEFAULT_WORKERS) + + return count + + +def _num_cpus(): + ''' + Compatibility wrapper for calculating the number of CPU's + a unit has. + + @returns: int: number of CPU cores detected + ''' + try: + return psutil.cpu_count() + except AttributeError: + return psutil.NUM_CPUS + + class WorkerConfigContext(OSContextGenerator): - @property - def num_cpus(self): - # NOTE: use cpu_count if present (16.04 support) - if hasattr(psutil, 'cpu_count'): - return psutil.cpu_count() - else: - return psutil.NUM_CPUS - def __call__(self): - multiplier = config('worker-multiplier') or DEFAULT_MULTIPLIER - count = int(self.num_cpus * multiplier) - if multiplier > 0 and count == 0: - count = 1 - - if config('worker-multiplier') is None and is_container(): - # NOTE(jamespage): Limit unconfigured worker-multiplier - # to MAX_DEFAULT_WORKERS to avoid insane - # worker configuration in LXD containers - # on large servers - # Reference: https://pad.lv/1665270 - count = min(count, MAX_DEFAULT_WORKERS) - - ctxt = {"workers": count} + ctxt = {"workers": _calculate_workers()} return ctxt @@ -1264,7 +1283,7 @@ class WSGIWorkerConfigContext(WorkerConfigContext): def __init__(self, name=None, script=None, admin_script=None, public_script=None, process_weight=1.00, - admin_process_weight=0.75, public_process_weight=0.25): + admin_process_weight=0.25, public_process_weight=0.75): self.service_name = name self.user = name self.group = name @@ -1276,8 +1295,7 @@ class WSGIWorkerConfigContext(WorkerConfigContext): self.public_process_weight = public_process_weight def __call__(self): - multiplier = config('worker-multiplier') or 1 - total_processes = self.num_cpus * multiplier + total_processes = _calculate_workers() ctxt = { "service_name": self.service_name, "user": self.user, diff --git a/hooks/glance_relations.py b/hooks/glance_relations.py index f8e05d8e..3dfd348f 100755 --- a/hooks/glance_relations.py +++ b/hooks/glance_relations.py @@ -53,11 +53,10 @@ from charmhelpers.core.hookenv import ( relation_get, relation_set, relation_ids, + related_units, service_name, - unit_get, UnregisteredHookError, status_set, - network_get_primary_address, ) from charmhelpers.core.host import ( @@ -105,7 +104,8 @@ from charmhelpers.contrib.network.ip import ( get_netmask_for_address, get_iface_for_address, get_ipv6_addr, - is_ipv6 + is_ipv6, + get_relation_ip, ) from charmhelpers.contrib.openstack.ip import ( canonical_url, @@ -158,13 +158,14 @@ def db_joined(): sync_db_with_multi_ipv6_addresses(config('database'), config('database-user')) else: - host = None - try: - # NOTE: try to use network spaces - host = network_get_primary_address('shared-db') - except NotImplementedError: - # NOTE: fallback to private-address - host = unit_get('private-address') + # Avoid churn check for access-network early + access_network = None + for unit in related_units(): + access_network = relation_get(unit=unit, + attribute='access-network') + if access_network: + break + host = get_relation_ip('shared-db', cidr_network=access_network) relation_set(database=config('database'), username=config('database-user'), diff --git a/unit_tests/test_glance_relations.py b/unit_tests/test_glance_relations.py index cc774a8e..68fb4ec4 100644 --- a/unit_tests/test_glance_relations.py +++ b/unit_tests/test_glance_relations.py @@ -59,9 +59,8 @@ TO_PATCH = [ 'relation_ids', 'relation_set', 'relation_get', + 'related_units', 'service_name', - 'unit_get', - 'network_get_primary_address', # charmhelpers.core.host 'apt_install', 'apt_update', @@ -99,6 +98,7 @@ TO_PATCH = [ 'get_ipv6_addr', 'sync_db_with_multi_ipv6_addresses', 'delete_keyring', + 'get_relation_ip', ] @@ -107,7 +107,6 @@ class GlanceRelationTests(CharmTestCase): def setUp(self): super(GlanceRelationTests, self).setUp(relations, TO_PATCH) self.config.side_effect = self.test_config.get - self.network_get_primary_address.side_effect = NotImplementedError @patch.object(utils, 'config') @patch.object(utils, 'token_cache_pkgs') @@ -178,40 +177,15 @@ class GlanceRelationTests(CharmTestCase): self.git_install.assert_called_with(projects_yaml) def test_db_joined(self): - self.unit_get.return_value = 'glance.foohost.com' + self.get_relation_ip.return_value = '10.0.0.1' self.is_relation_made.return_value = False relations.db_joined() self.relation_set.assert_called_with(database='glance', username='glance', - hostname='glance.foohost.com') - self.unit_get.assert_called_with('private-address') - - def test_db_joined_network_spaces(self): - self.network_get_primary_address.side_effect = None - self.network_get_primary_address.return_value = '192.168.20.1' - self.unit_get.return_value = 'glance.foohost.com' - self.is_relation_made.return_value = False - relations.db_joined() - self.relation_set.assert_called_with(database='glance', - username='glance', - hostname='192.168.20.1') - self.assertFalse(self.unit_get.called) - - def test_db_joined_with_ipv6(self): - self.test_config.set('prefer-ipv6', True) - self.is_relation_made.return_value = False - relations.db_joined() - relation_data = { - 'database': 'glance', - 'username': 'glance', - } - relation_data['hostname'] = '2001:db8:1::1' - - self.sync_db_with_multi_ipv6_addresses.assert_called_with( - 'glance', 'glance') + hostname='10.0.0.1') + self.get_relation_ip.assert_called_with('shared-db', cidr_network=None) def test_postgresql_db_joined(self): - self.unit_get.return_value = 'glance.foohost.com' self.is_relation_made.return_value = False relations.pgsql_db_joined() self.relation_set.assert_called_with(database='glance'),