[ivoks,r=james-page] Re-order port pipeline to ensure that SSL occurs end-to-end.

This commit is contained in:
James Page 2014-02-19 10:44:30 +00:00
commit 0acdc2df8a
8 changed files with 68 additions and 43 deletions

View File

@ -126,17 +126,17 @@ def determine_api_port(public_port):
return public_port - (i * 10)
def determine_haproxy_port(public_port):
def determine_apache_port(public_port):
'''
Description: Determine correct proxy listening port based on public IP +
existence of HTTPS reverse proxy.
Description: Determine correct apache listening port based on public IP +
state of the cluster.
public_port: int: standard public port for given service
returns: int: the correct listening port for the HAProxy service
'''
i = 0
if https():
if len(peer_units()) > 0 or is_clustered():
i += 1
return public_port - (i * 10)

View File

@ -26,11 +26,9 @@ from charmhelpers.core.hookenv import (
)
from charmhelpers.contrib.hahelpers.cluster import (
determine_apache_port,
determine_api_port,
determine_haproxy_port,
https,
is_clustered,
peer_units,
)
from charmhelpers.contrib.hahelpers.apache import (
@ -218,7 +216,12 @@ class AMQPContext(OSContextGenerator):
# Sufficient information found = break out!
break
# Used for active/active rabbitmq >= grizzly
if 'clustered' not in ctxt and len(related_units(rid)) > 1:
if ('clustered' not in ctxt or relation_get('ha-vip-only') == 'True') and \
len(related_units(rid)) > 1:
if relation_get('ha_queues'):
ctxt['rabbitmq_ha_queues'] = relation_get('ha_queues')
else:
ctxt['rabbitmq_ha_queues'] = False
rabbitmq_hosts = []
for unit in related_units(rid):
rabbitmq_hosts.append(relation_get('private-address',
@ -380,11 +383,9 @@ class ApacheSSLContext(OSContextGenerator):
'private_address': unit_get('private-address'),
'endpoints': []
}
for ext_port in self.external_ports:
if peer_units() or is_clustered():
int_port = determine_haproxy_port(ext_port)
else:
int_port = determine_api_port(ext_port)
for api_port in self.external_ports:
ext_port = determine_apache_port(api_port)
int_port = determine_api_port(api_port)
portmap = (int(ext_port), int(int_port))
ctxt['endpoints'].append(portmap)
return ctxt
@ -586,6 +587,7 @@ class SubordinateConfigContext(OSContextGenerator):
class SyslogContext(OSContextGenerator):
def __call__(self):
ctxt = {
'use_syslog': config('use-syslog')

View File

@ -8,8 +8,8 @@ global
defaults
log global
mode http
option httplog
mode tcp
option tcplog
option dontlognull
retries 3
timeout queue 1000
@ -29,7 +29,6 @@ listen stats :8888
{% for service, ports in service_ports.iteritems() -%}
listen {{ service }} 0.0.0.0:{{ ports[0] }}
balance roundrobin
option tcplog
{% for unit, address in units.iteritems() -%}
server {{ unit }} {{ address }}:{{ ports[1] }} check
{% endfor %}

View File

@ -194,7 +194,7 @@ def file_hash(path):
return None
def restart_on_change(restart_map):
def restart_on_change(restart_map, stopstart=False):
"""Restart services based on configuration files changing
This function is used a decorator, for example
@ -219,8 +219,14 @@ def restart_on_change(restart_map):
for path in restart_map:
if checksums[path] != file_hash(path):
restarts += restart_map[path]
for service_name in list(OrderedDict.fromkeys(restarts)):
service('restart', service_name)
services_list = list(OrderedDict.fromkeys(restarts))
if not stopstart:
for service_name in services_list:
service('restart', service_name)
else:
for action in ['stop', 'start']:
for service_name in services_list:
service(action, service_name)
return wrapped_f
return wrap

View File

@ -10,8 +10,8 @@ from charmhelpers.contrib.openstack.context import (
)
from charmhelpers.contrib.hahelpers.cluster import (
determine_apache_port,
determine_api_port,
determine_haproxy_port,
)
@ -54,11 +54,12 @@ class HAProxyContext(OSContextGenerator):
specific to this charm.
Also used to extend cinder.conf context with correct api_listening_port
'''
haproxy_port = determine_haproxy_port(config('api-listening-port'))
haproxy_port = config('api-listening-port')
api_port = determine_api_port(config('api-listening-port'))
apache_port = determine_apache_port(config('api-listening-port'))
ctxt = {
'service_ports': {'cinder_api': [haproxy_port, api_port]},
'service_ports': {'cinder_api': [haproxy_port, apache_port]},
'osapi_volume_listen_port': api_port,
}
return ctxt

View File

@ -80,7 +80,7 @@ def install():
@hooks.hook('config-changed')
@restart_on_change(restart_map())
@restart_on_change(restart_map(), stopstart=True)
def config_changed():
if openstack_upgrade_available('cinder-common'):
do_openstack_upgrade(configs=CONFIGS)
@ -183,7 +183,7 @@ def ceph_changed():
@hooks.hook('cluster-relation-changed',
'cluster-relation-departed')
@restart_on_change(restart_map())
@restart_on_change(restart_map(), stopstart=True)
def cluster_changed():
CONFIGS.write_all()
@ -242,7 +242,7 @@ def image_service_changed():
'identity-service-relation-broken',
'image-service-relation-broken',
'shared-db-relation-broken')
@restart_on_change(restart_map())
@restart_on_change(restart_map(), stopstart=True)
def relation_broken():
CONFIGS.write_all()

View File

@ -10,7 +10,7 @@ TO_PATCH = [
'config',
'relation_ids',
'service_name',
'determine_haproxy_port',
'determine_apache_port',
'determine_api_port',
]
@ -50,23 +50,35 @@ class TestCinderContext(CharmTestCase):
'rbd_user': service,
'host': service})
def test_haproxy_configuration(self):
self.determine_haproxy_port.return_value = 8080
self.determine_api_port.return_value = 8090
self.assertEquals(
contexts.HAProxyContext()(),
{'service_ports': {'cinder_api': [8080, 8090]},
'osapi_volume_listen_port': 8090})
@patch.object(utils, 'service_enabled')
def test_apache_ssl_context_service_disabled(self, service_enabled):
service_enabled.return_value = False
self.assertEquals(contexts.ApacheSSLContext()(), {})
@patch('charmhelpers.contrib.openstack.context.determine_apache_port')
@patch('charmhelpers.contrib.openstack.context.determine_api_port')
@patch('charmhelpers.contrib.openstack.context.unit_get')
@patch('charmhelpers.contrib.openstack.context.https')
@patch.object(utils, 'service_enabled')
def test_apache_ssl_context_service_enabled(self, service_enabled,
https):
service_enabled.return_value = True
https.return_value = False
self.assertEquals(contexts.ApacheSSLContext()(), {})
mock_https, mock_unit_get,
mock_determine_api_port,
mock_determine_apache_port):
mock_https.return_value = True
mock_unit_get.return_value = '1.2.3.4'
mock_determine_api_port.return_value = '12'
mock_determine_apache_port.return_value = '34'
ctxt = contexts.ApacheSSLContext()
with patch.object(ctxt, 'enable_modules') as mock_enable_modules:
with patch.object(ctxt, 'configure_cert') as mock_configure_cert:
service_enabled.return_value = False
self.assertEquals(ctxt(), {})
self.assertFalse(mock_https.called)
service_enabled.return_value = True
self.assertEquals(ctxt(), {'endpoints': [(34, 12)],
'private_address': '1.2.3.4',
'namespace': 'cinder'})
self.assertTrue(mock_https.called)
mock_unit_get.assert_called_with('private-address')

View File

@ -74,11 +74,16 @@ class TestClusterHooks(CharmTestCase):
file_hash.side_effect = side_effects
hooks.hooks.execute(['hooks/cluster-relation-changed'])
ex = [
call('restart', 'cinder-api'),
call('restart', 'cinder-volume'),
call('restart', 'cinder-scheduler'),
call('restart', 'haproxy'),
call('restart', 'apache2')]
call('stop', 'cinder-api'),
call('stop', 'cinder-volume'),
call('stop', 'cinder-scheduler'),
call('stop', 'haproxy'),
call('stop', 'apache2'),
call('start', 'cinder-api'),
call('start', 'cinder-volume'),
call('start', 'cinder-scheduler'),
call('start', 'haproxy'),
call('start', 'apache2')]
self.assertEquals(ex, service.call_args_list)
def test_ha_joined_complete_config(self):