diff --git a/hooks/charmhelpers/contrib/openstack/context.py b/hooks/charmhelpers/contrib/openstack/context.py index f67f3265..e9543638 100644 --- a/hooks/charmhelpers/contrib/openstack/context.py +++ b/hooks/charmhelpers/contrib/openstack/context.py @@ -41,9 +41,9 @@ from charmhelpers.core.hookenv import ( charm_name, DEBUG, INFO, + WARNING, ERROR, status_set, - network_get_primary_address ) from charmhelpers.core.sysctl import create as sysctl_create @@ -80,9 +80,6 @@ from charmhelpers.contrib.openstack.neutron import ( from charmhelpers.contrib.openstack.ip import ( resolve_address, INTERNAL, - ADMIN, - PUBLIC, - ADDRESS_MAP, ) from charmhelpers.contrib.network.ip import ( get_address_in_network, @@ -90,6 +87,7 @@ from charmhelpers.contrib.network.ip import ( get_ipv6_addr, get_netmask_for_address, format_ipv6_addr, + is_address_in_network, is_bridge_member, is_ipv6_disabled, ) @@ -622,6 +620,7 @@ class HAProxyContext(OSContextGenerator): ctxt['haproxy_connect_timeout'] = config('haproxy-connect-timeout') if config('prefer-ipv6'): + ctxt['ipv6'] = True ctxt['local_host'] = 'ip6-localhost' ctxt['haproxy_host'] = '::' else: @@ -759,27 +758,36 @@ class ApacheSSLContext(OSContextGenerator): ...] """ addresses = [] - for net_type in [INTERNAL, ADMIN, PUBLIC]: - net_config = config(ADDRESS_MAP[net_type]['config']) - # NOTE(jamespage): Fallback must always be private address - # as this is used to bind services on the - # local unit. - fallback = unit_get("private-address") - if net_config: - addr = get_address_in_network(net_config, - fallback) + if config('vip'): + vips = config('vip').split() + else: + vips = [] + + for net_type in ['internal', 'admin', 'public']: + net_config = config('os-{}-network'.format(net_type)) + addr = get_address_in_network(net_config, + unit_get('private-address')) + + hostname_config = config('os-{}-hostname'.format(net_type)) + if hostname_config: + addresses.append((addr, hostname_config)) + elif len(vips) > 1 and is_clustered(): + if not net_config: + log("Multiple networks configured but net_type " + "is None (%s)." % net_type, level=WARNING) + continue + + for vip in vips: + if is_address_in_network(net_config, vip): + addresses.append((addr, vip)) + break + + elif is_clustered() and config('vip'): + addresses.append((addr, config('vip'))) else: - try: - addr = network_get_primary_address( - ADDRESS_MAP[net_type]['binding'] - ) - except NotImplementedError: - addr = fallback + addresses.append((addr, addr)) - endpoint = resolve_address(net_type) - addresses.append((addr, endpoint)) - - return sorted(set(addresses)) + return sorted(addresses) def __call__(self): if isinstance(self.external_ports, six.string_types): @@ -806,7 +814,7 @@ class ApacheSSLContext(OSContextGenerator): self.configure_cert(cn) addresses = self.get_network_addresses() - for address, endpoint in addresses: + for address, endpoint in sorted(set(addresses)): for api_port in self.external_ports: ext_port = determine_apache_port(api_port, singlenode_mode=True) diff --git a/hooks/neutron_contexts.py b/hooks/neutron_contexts.py index 08444c00..77401e4f 100644 --- a/hooks/neutron_contexts.py +++ b/hooks/neutron_contexts.py @@ -94,6 +94,7 @@ class NeutronGatewayContext(NeutronAPIContext): 'l2_population': api_settings['l2_population'], 'enable_dvr': api_settings['enable_dvr'], 'enable_l3ha': api_settings['enable_l3ha'], + 'extension_drivers': api_settings['extension_drivers'], 'dns_domain': api_settings['dns_domain'], 'overlay_network_type': api_settings['overlay_network_type'], diff --git a/templates/mitaka/openvswitch_agent.ini b/templates/mitaka/openvswitch_agent.ini index 499427a5..b703d3dc 100644 --- a/templates/mitaka/openvswitch_agent.ini +++ b/templates/mitaka/openvswitch_agent.ini @@ -14,6 +14,9 @@ l2_population = {{ l2_population }} enable_distributed_routing = {{ enable_dvr }} {% if veth_mtu -%} veth_mtu = {{ veth_mtu }} +{% endif -%} +{% if extension_drivers -%} +extensions = {{ extension_drivers }} {% endif %} [securitygroup] diff --git a/tests/basic_deployment.py b/tests/basic_deployment.py index e4d297be..0d3d64bd 100644 --- a/tests/basic_deployment.py +++ b/tests/basic_deployment.py @@ -90,6 +90,8 @@ class NeutronGatewayBasicDeployment(OpenStackAmuletDeployment): 'rabbitmq-server:amqp': 'neutron-openvswitch:amqp', 'nova-compute:image-service': 'glance:image-service', 'nova-cloud-controller:image-service': 'glance:image-service', + 'neutron-api:neutron-plugin-api': 'neutron-gateway:' + 'neutron-plugin-api', } super(NeutronGatewayBasicDeployment, self)._add_relations(relations) @@ -615,7 +617,7 @@ class NeutronGatewayBasicDeployment(OpenStackAmuletDeployment): }, 'agent': { 'tunnel_types': 'gre', - 'l2_population': 'False' + 'l2_population': 'True' }, 'securitygroup': { 'firewall_driver': 'neutron.agent.linux.iptables_firewall.' @@ -631,7 +633,7 @@ class NeutronGatewayBasicDeployment(OpenStackAmuletDeployment): }, 'agent': { 'tunnel_types': 'gre', - 'l2_population': 'False' + 'l2_population': 'True' }, 'securitygroup': { 'firewall_driver': 'neutron.agent.linux.iptables_firewall.' @@ -969,6 +971,28 @@ class NeutronGatewayBasicDeployment(OpenStackAmuletDeployment): u.log.debug('Deleting neutron network...') self.neutron.delete_network(network['id']) + def test_401_enable_qos(self): + """Check qos settings set via neutron-api charm""" + if self._get_openstack_release() >= self.trusty_mitaka: + unit = self.neutron_gateway_sentry + set_default = {'enable-qos': 'False'} + set_alternate = {'enable-qos': 'True'} + self.d.configure('neutron-api', set_alternate) + time.sleep(60) + self._auto_wait_for_status(exclude_services=self.exclude_services) + config = u._get_config( + unit, + '/etc/neutron/plugins/ml2/openvswitch_agent.ini') + extensions = config.get('agent', 'extensions').split(',') + if 'qos' not in extensions: + message = "qos not in extensions" + amulet.raise_status(amulet.FAIL, msg=message) + + u.log.debug('Setting QoS back to {}'.format( + set_default['enable-qos'])) + self.d.configure('neutron-api', set_default) + u.log.debug('OK') + def test_900_restart_on_config_change(self): """Verify that the specified services are restarted when the config is changed.""" diff --git a/unit_tests/test_neutron_contexts.py b/unit_tests/test_neutron_contexts.py index e0a9c4ba..23a55ff1 100644 --- a/unit_tests/test_neutron_contexts.py +++ b/unit_tests/test_neutron_contexts.py @@ -154,6 +154,7 @@ class TestNeutronGatewayContext(CharmTestCase): 'enable-dvr': 'True', 'overlay-network-type': 'gre', 'enable-l3ha': 'True', + 'enable-qos': 'True', 'network-device-mtu': 9000, 'dns-domain': 'openstack.example.'} self.test_config.set('plugin', 'ovs') @@ -179,6 +180,7 @@ class TestNeutronGatewayContext(CharmTestCase): 'enable_dvr': True, 'enable_l3ha': True, 'dns_servers': '8.8.8.8,4.4.4.4', + 'extension_drivers': 'qos', 'dns_domain': 'openstack.example.', 'local_ip': '10.5.0.1', 'instance_mtu': 1420, @@ -212,6 +214,7 @@ class TestNeutronGatewayContext(CharmTestCase): 'enable-dvr': 'True', 'overlay-network-type': 'gre', 'enable-l3ha': 'True', + 'enable-qos': 'True', 'network-device-mtu': 9000, 'dns-domain': 'openstack.example.'} self.test_config.set('plugin', 'ovs') @@ -236,6 +239,7 @@ class TestNeutronGatewayContext(CharmTestCase): 'enable_dvr': True, 'enable_l3ha': True, 'dns_servers': None, + 'extension_drivers': 'qos', 'dns_domain': 'openstack.example.', 'local_ip': '192.168.20.2', 'instance_mtu': 1420,