diff --git a/manifests/dashboard.pp b/manifests/dashboard.pp index 5d2c901d..4a35d2c4 100644 --- a/manifests/dashboard.pp +++ b/manifests/dashboard.pp @@ -138,7 +138,7 @@ class cloud::dashboard( server_names => $::hostname, ipaddresses => $api_eth, ports => $horizon_port, - options => 'check inter 2000 rise 2 fall 5' + options => "check inter 2000 rise 2 fall 5 cookie ${::hostname}" } diff --git a/manifests/loadbalancer.pp b/manifests/loadbalancer.pp index 921f439b..9e539c4b 100644 --- a/manifests/loadbalancer.pp +++ b/manifests/loadbalancer.pp @@ -51,108 +51,111 @@ # # [*swift_api*] # (optional) Enable or not Swift public binding. +# If true, both public and internal will attempt to be created except if vip_internal_ip is set to false (backward compatibility). +# If set to ['10.0.0.1'], only IP in the array (or in the string) will be configured in the pool. They must be part of keepalived_ip options. +# If set to false, no binding will be configure # Defaults to true # # [*ceilometer_api*] # (optional) Enable or not Ceilometer public binding. +# If true, both public and internal will attempt to be created except if vip_internal_ip is set to false (backward compatibility). +# If set to ['10.0.0.1'], only IP in the array (or in the string) will be configured in the pool. They must be part of keepalived_ip options. +# If set to false, no binding will be configure # Defaults to true # # [*cinder_api*] # (optional) Enable or not Cinder public binding. +# If true, both public and internal will attempt to be created except if vip_internal_ip is set to false (backward compatibility). +# If set to ['10.0.0.1'], only IP in the array (or in the string) will be configured in the pool. They must be part of keepalived_ip options. +# If set to false, no binding will be configure # Defaults to true # # [*glance_api*] # (optional) Enable or not Glance API public binding. +# If true, both public and internal will attempt to be created except if vip_internal_ip is set to false (backward compatibility). +# If set to ['10.0.0.1'], only IP in the array (or in the string) will be configured in the pool. They must be part of keepalived_ip options. +# If set to false, no binding will be configure # Defaults to true # # [*glance_registry*] # (optional) Enable or not Glance Registry public binding. +# If true, both public and internal will attempt to be created except if vip_internal_ip is set to false (backward compatibility). +# If set to ['10.0.0.1'], only IP in the array (or in the string) will be configured in the pool. They must be part of keepalived_ip options. +# If set to false, no binding will be configure # Defaults to true # # [*neutron_api*] # (optional) Enable or not Neutron public binding. +# If true, both public and internal will attempt to be created except if vip_internal_ip is set to false (backward compatibility). +# If set to ['10.0.0.1'], only IP in the array (or in the string) will be configured in the pool. They must be part of keepalived_ip options. +# If set to false, no binding will be configure # Defaults to true # # [*heat_api*] # (optional) Enable or not Heat public binding. +# If true, both public and internal will attempt to be created except if vip_internal_ip is set to false (backward compatibility). +# If set to ['10.0.0.1'], only IP in the array (or in the string) will be configured in the pool. They must be part of keepalived_ip options. +# If set to false, no binding will be configure # Defaults to true # # [*heat_cfn_api*] # (optional) Enable or not Heat CFN public binding. +# If true, both public and internal will attempt to be created except if vip_internal_ip is set to false (backward compatibility). +# If set to ['10.0.0.1'], only IP in the array (or in the string) will be configured in the pool. They must be part of keepalived_ip options. +# If set to false, no binding will be configure # Defaults to true # # [*heat_cloudwatch_api*] # (optional) Enable or not Heat Cloudwatch public binding. +# If true, both public and internal will attempt to be created except if vip_internal_ip is set to false (backward compatibility). +# If set to ['10.0.0.1'], only IP in the array (or in the string) will be configured in the pool. They must be part of keepalived_ip options. +# If set to false, no binding will be configure # Defaults to true # # [*nova_api*] # (optional) Enable or not Nova public binding. +# If true, both public and internal will attempt to be created except if vip_internal_ip is set to false (backward compatibility). +# If set to ['10.0.0.1'], only IP in the array (or in the string) will be configured in the pool. They must be part of keepalived_ip options. +# If set to false, no binding will be configure # Defaults to true # # [*ec2_api*] # (optional) Enable or not EC2 public binding. +# If true, both public and internal will attempt to be created except if vip_internal_ip is set to false (backward compatibility). +# If set to ['10.0.0.1'], only IP in the array (or in the string) will be configured in the pool. They must be part of keepalived_ip options. +# If set to false, no binding will be configure # Defaults to true # # [*metadata_api*] # (optional) Enable or not Metadata public binding. +# If true, both public and internal will attempt to be created except if vip_internal_ip is set to false (backward compatibility). +# If set to ['10.0.0.1'], only IP in the array (or in the string) will be configured in the pool. They must be part of keepalived_ip options. +# If set to false, no binding will be configure # Defaults to true # # [*keystone_api*] # (optional) Enable or not Keystone public binding. +# If true, both public and internal will attempt to be created except if vip_internal_ip is set to false (backward compatibility). +# If set to ['10.0.0.1'], only IP in the array (or in the string) will be configured in the pool. They must be part of keepalived_ip options. +# If set to false, no binding will be configure # Defaults to true # # [*keystone_api_admin*] # (optional) Enable or not Keystone admin binding. +# If true, both public and internal will attempt to be created except if vip_internal_ip is set to false (backward compatibility). +# If set to ['10.0.0.1'], only IP in the array (or in the string) will be configured in the pool. They must be part of keepalived_ip options. +# If set to false, no binding will be configure # Defaults to true # -# [*keystone_api_internal*] -# (optional) Enable or not Keystone internal binding. -# Defaults to true -# -# [*cinder_api_internal*] -# (optional) Enable or not Cinder internal binding. -# Defaults to true -# -# [*ceilometer_api_internal*] -# (optional) Enable or not Ceilometer internal binding. -# Defaults to true -# -# [*glance_api_internal*] -# (optional) Enable or not Glance API internal binding. -# Defaults to true -# -# [*glance_registry_internal*] -# (optional) Enable or not Glance Registry internal binding. -# Defaults to true -# -# [*nova_api_internal*] -# (optional) Enable or not Nova internal binding. -# Defaults to true -# -# [*ec2_api_internal*] -# (optional) Enable or not EC2 internal binding. -# Defaults to true -# -# [*neutron_api_internal*] -# (optional) Enable or not Neutron internal binding. -# Defaults to true -# -# [*swift_api_internal*] -# (optional) Enable or not Swift internal binding. -# Defaults to true -# -# [*heat_api_internal*] -# (optional) Enable or not Heat internal binding. -# Defaults to true -# -# [*heat_cfn_api_internal*] -# (optional) Enable or not Heat CFN internal binding. -# Defaults to true -# -# [*heat_cloudwatch_api_internal*] -# (optional) Enable or not Heat Cloudwatch internal binding. -# Defaults to true +# [*vip_public_ip*] +# (optional) Array or string for public VIP +# Should be part of keepalived_public_ips +# Defaults to '127.0.0.2' # +# [*vip_internal_ip*] +# (optional) Array or string for internal VIP +# Should be part of keepalived_internal_ips +# Defaults to false (backward compatibility) class cloud::loadbalancer( $swift_api = true, $ceilometer_api = true, @@ -167,62 +170,36 @@ class cloud::loadbalancer( $ec2_api = true, $metadata_api = true, $keystone_api = true, - $swift_api_internal = true, - $ceilometer_api_internal = true, - $cinder_api_internal = true, - $glance_api_internal = true, - $glance_registry_internal = true, - $neutron_api_internal = true, - $heat_api_internal = true, - $heat_cfn_api_internal = true, - $heat_cloudwatch_api_internal = true, - $nova_api_internal = true, - $ec2_api_internal = true, - $metadata_api_internal = true, - $keystone_api_internal = true, $keystone_api_admin = true, $horizon = true, $horizon_ssl = false, $spice = true, $haproxy_auth = 'admin:changeme', $keepalived_state = 'BACKUP', - $keepalived_priority = 50, + $keepalived_priority = '50', $keepalived_public_interface = 'eth0', $keepalived_public_ipvs = ['127.0.0.1'], $keepalived_internal_interface = 'eth1', $keepalived_internal_ipvs = false, - $ks_ceilometer_internal_port = 8777, $ks_ceilometer_public_port = 8777, - $ks_cinder_internal_port = 8776, $ks_cinder_public_port = 8776, - $ks_ec2_internal_port = 8773, $ks_ec2_public_port = 8773, - $ks_glance_api_internal_port = 9292, $ks_glance_api_public_port = 9292, $ks_glance_registry_internal_port = 9191, - $ks_glance_registry_public_port = 9191, - $ks_heat_cfn_internal_port = 8000, $ks_heat_cfn_public_port = 8000, - $ks_heat_cloudwatch_internal_port = 8003, $ks_heat_cloudwatch_public_port = 8003, - $ks_heat_internal_port = 8004, $ks_heat_public_port = 8004, $ks_keystone_admin_port = 35357, - $ks_keystone_internal_port = 5000, $ks_keystone_public_port = 5000, - $ks_metadata_internal_port = 8775, $ks_metadata_public_port = 8775, - $ks_neutron_internal_port = 9696, $ks_neutron_public_port = 9696, - $ks_nova_internal_port = 8774, $ks_nova_public_port = 8774, - $ks_swift_internal_port = 8080, $ks_swift_public_port = 8080, $horizon_port = 80, $spice_port = 6082, - $vip_public_ip = '127.0.0.2', + $vip_public_ip = ['127.0.0.1'], $vip_internal_ip = false, - $galera_ip = '127.0.0.1', + $galera_ip = ['127.0.0.1'], # Deprecated parameters $keepalived_interface = false, $keepalived_ipvs = false, @@ -254,8 +231,11 @@ class cloud::loadbalancer( } # Ensure Keepalived is started before HAproxy to avoid binding errors. + # HAproxy is managed by Keepalived. class { 'keepalived': } -> - class { 'haproxy': } + class { 'haproxy': + service_manage => false + } keepalived::vrrp_script { 'haproxy': name_is_process => true @@ -302,226 +282,88 @@ class cloud::loadbalancer( } } - if $keystone_api { - cloud::loadbalancer::listen_http { - 'keystone_api_cluster': - ports => $ks_keystone_public_port, - listen_ip => $vip_public_ip; - 'keystone_api_admin_cluster': - ports => $ks_keystone_admin_port, - listen_ip => $vip_public_ip; - } + # Instanciate HAproxy binding + cloud::loadbalancer::binding { 'keystone_api_cluster': + ip => $keystone_api, + port => $ks_keystone_public_port; } - if $keystone_api_internal and $vip_internal_ip and $keepalived_internal_ipvs { - cloud::loadbalancer::listen_http { - 'keystone_api_internal_cluster': - ports => $ks_keystone_internal_port, - listen_ip => $vip_internal_ip; - } + cloud::loadbalancer::binding { 'keystone_api_admin_cluster': + ip => $keystone_api_admin, + port => $ks_keystone_admin_port; } - - if $swift_api { - cloud::loadbalancer::listen_http{ - 'swift_api_cluster': - ports => $ks_swift_public_port, - httpchk => 'httpchk /healthcheck', - listen_ip => $vip_public_ip; - } + cloud::loadbalancer::binding { 'swift_api_cluster': + ip => $swift_api, + port => $ks_swift_public_port, + httpchk => 'httpchk /healthcheck'; } - if $swift_api_internal and $vip_internal_ip and $keepalived_internal_ipvs { - cloud::loadbalancer::listen_http { - 'swift_api_internal_cluster': - ports => $ks_swift_internal_port, - listen_ip => $vip_internal_ip; - } + cloud::loadbalancer::binding { 'nova_api_cluster': + ip => $nova_api, + port => $ks_nova_public_port; } - - if $nova_api { - cloud::loadbalancer::listen_http{ - 'nova_api_cluster': - ports => $ks_nova_public_port, - listen_ip => $vip_public_ip; - } + cloud::loadbalancer::binding { 'ec2_api_cluster': + ip => $ec2_api, + port => $ks_ec2_public_port; } - if $nova_api_internal and $vip_internal_ip and $keepalived_internal_ipvs { - cloud::loadbalancer::listen_http { - 'nova_api_internal_cluster': - ports => $ks_nova_internal_port, - listen_ip => $vip_internal_ip; - } + cloud::loadbalancer::binding { 'metadata_api_cluster': + ip => $metadata_api, + port => $ks_metadata_public_port; } - - if $ec2_api { - cloud::loadbalancer::listen_http{ - 'ec2_api_cluster': - ports => $ks_ec2_public_port, - listen_ip => $vip_public_ip; - } + cloud::loadbalancer::binding { 'spice_cluster': + ip => $spice, + port => $spice_port, + httpchk => 'httpchk GET /'; } - if $ec2_api_internal and $vip_internal_ip and $keepalived_internal_ipvs { - cloud::loadbalancer::listen_http { - 'ec2_api_internal_cluster': - ports => $ks_ec2_internal_port, - listen_ip => $vip_internal_ip; - } + cloud::loadbalancer::binding { 'glance_api_cluster': + ip => $glance_api, + port => $ks_glance_api_public_port; } - - if $metadata_api { - cloud::loadbalancer::listen_http{ - 'metadata_api_cluster': - ports => $ks_metadata_public_port, - listen_ip => $vip_public_ip; - } + cloud::loadbalancer::binding { 'glance_registry_cluster': + ip => $glance_registry, + port => $ks_glance_registry_internal_port; } - if $metadata_api_internal and $vip_internal_ip and $keepalived_internal_ipvs { - cloud::loadbalancer::listen_http { - 'metadata_api_internal_cluster': - ports => $ks_metadata_internal_port, - listen_ip => $vip_internal_ip; - } + cloud::loadbalancer::binding { 'neutron_api_cluster': + ip => $neutron_api, + port => $ks_neutron_public_port; } - - if $spice { - cloud::loadbalancer::listen_http{ - 'spice_cluster': - ports => $spice_port, - listen_ip => $vip_public_ip, - httpchk => 'httpchk GET /'; - } + cloud::loadbalancer::binding { 'cinder_api_cluster': + ip => $cinder_api, + port => $ks_cinder_public_port; } - if $glance_api { - cloud::loadbalancer::listen_http{ - 'glance_api_cluster': - ports => $ks_glance_api_public_port, - listen_ip => $vip_public_ip; - } + cloud::loadbalancer::binding { 'ceilometer_api_cluster': + ip => $ceilometer_api, + port => $ks_ceilometer_public_port; } - if $glance_api_internal and $vip_internal_ip and $keepalived_internal_ipvs { - cloud::loadbalancer::listen_http { - 'glance_api_internal_cluster': - ports => $ks_glance_api_internal_port, - listen_ip => $vip_internal_ip; - } + cloud::loadbalancer::binding { 'heat_api_cluster': + ip => $heat_api, + port => $ks_heat_public_port; } - - if $glance_registry { - warning('Glance Registry should not be exposed to public network.') - cloud::loadbalancer::listen_http{ - 'glance_registry_cluster': - ports => $ks_glance_registry_internal_port, - listen_ip => $vip_public_ip; - } + cloud::loadbalancer::binding { 'heat_cfn_api_cluster': + ip => $heat_cfn_api, + port => $ks_heat_cfn_public_port; } - if $glance_api_internal and $vip_internal_ip and $keepalived_internal_ipvs { - cloud::loadbalancer::listen_http { - 'glance_api_internal_cluster': - ports => $ks_glance_api_internal_port, - listen_ip => $vip_internal_ip; - } - } - - if $neutron_api { - cloud::loadbalancer::listen_http{ - 'neutron_api_cluster': - ports => $ks_neutron_public_port, - listen_ip => $vip_public_ip; - } - } - if $neutron_api_internal and $vip_internal_ip and $keepalived_internal_ipvs { - cloud::loadbalancer::listen_http { - 'neutron_api_internal_cluster': - ports => $ks_neutron_internal_port, - listen_ip => $vip_internal_ip; - } - } - - if $cinder_api { - cloud::loadbalancer::listen_http{ - 'cinder_api_cluster': - ports => $ks_cinder_public_port, - listen_ip => $vip_public_ip; - } - } - if $cinder_api_internal and $vip_internal_ip and $keepalived_internal_ipvs { - cloud::loadbalancer::listen_http { - 'cinder_api_internal_cluster': - ports => $ks_cinder_internal_port, - listen_ip => $vip_internal_ip; - } - } - - if $ceilometer_api { - cloud::loadbalancer::listen_http{ - 'ceilometer_api_cluster': - ports => $ks_ceilometer_public_port, - listen_ip => $vip_public_ip; - } - } - if $ceilometer_api_internal and $vip_internal_ip and $keepalived_internal_ipvs { - cloud::loadbalancer::listen_http { - 'ceilometer_api_internal_cluster': - ports => $ks_ceilometer_internal_port, - listen_ip => $vip_internal_ip; - } - } - - if $heat_api { - cloud::loadbalancer::listen_http{ - 'heat_api_cluster': - ports => $ks_heat_public_port, - listen_ip => $vip_public_ip; - } - } - if $heat_api_internal and $vip_internal_ip and $keepalived_internal_ipvs { - cloud::loadbalancer::listen_http { - 'heat_api_internal_cluster': - ports => $ks_heat_internal_port, - listen_ip => $vip_internal_ip; - } - } - - if $heat_cfn_api { - cloud::loadbalancer::listen_http{ - 'heat_api_cfn_cluster': - ports => $ks_heat_cfn_public_port, - listen_ip => $vip_public_ip; - } - } - if $heat_cfn_api_internal and $vip_internal_ip and $keepalived_internal_ipvs { - cloud::loadbalancer::listen_http { - 'heat_cfn_internal_cluster': - ports => $ks_heat_cfn_internal_port, - listen_ip => $vip_internal_ip; - } - } - - if $heat_cloudwatch_api { - cloud::loadbalancer::listen_http{ - 'heat_api_cloudwatch_cluster': - ports => $ks_heat_cloudwatch_public_port, - listen_ip => $vip_public_ip; - } - } - if $heat_cloudwatch_api_internal and $vip_internal_ip and $keepalived_internal_ipvs { - cloud::loadbalancer::listen_http { - 'heat_cloudwatch_internal_cluster': - ports => $ks_heat_cloudwatch_internal_port, - listen_ip => $vip_internal_ip; - } + cloud::loadbalancer::binding { 'heat_cloudwatch_api_cluster': + ip => $heat_cloudwatch_api, + port => $ks_heat_cloudwatch_public_port; } if $horizon { if $horizon_ssl { - cloud::loadbalancer::listen_https{ - 'horizon_cluster': - ports => $horizon_port, - listen_ip => $vip_public_ip; + cloud::loadbalancer::listen_https{ 'horizon_cluster': + ports => $horizon_port, + listen_ip => $vip_public_ip; } } else { - cloud::loadbalancer::listen_http{ - 'horizon_cluster': - ports => $horizon_port, - listen_ip => $vip_public_ip; + # Horizon URL is not the same on Red Hat and Debian/Ubuntu + if $::operatingsystem == 'RedHat' { + $horizon_auth_url = 'dashboard' + } else { + $horizon_auth_url = 'horizon' + } + cloud::loadbalancer::listen_http{ 'horizon_cluster': + ports => $horizon_port, + httpchk => "httpchk GET /$horizon_auth_url HTTP/1.0\r\nUser-Agent:\ HAproxy-${::hostname}", + options => { 'cookie' => 'sessionid prefix', 'balance' => 'leastconn' }, + listen_ip => $vip_public_ip; } } } diff --git a/manifests/loadbalancer/binding.pp b/manifests/loadbalancer/binding.pp new file mode 100644 index 00000000..74a15903 --- /dev/null +++ b/manifests/loadbalancer/binding.pp @@ -0,0 +1,63 @@ +# +# Copyright (C) 2014 eNovance SAS +# +# Author: Emilien Macchi +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +define cloud::loadbalancer::binding ( + $ip, + $port, + $httpchk = undef +){ + + include cloud::loadbalancer + + # join all VIP together + $vip_public_ip_array = any2array($::cloud::loadbalancer::vip_public_ip) + $vip_internal_ip_array = any2array($::cloud::loadbalancer::vip_internal_ip) + if $::cloud::loadbalancer::vip_public_ip and $::cloud::loadbalancer::vip_internal_ip { + $all_vip_array = union($vip_public_ip_array, $vip_internal_ip_array) + } + if $::cloud::loadbalancer::vip_public_ip and ! $::cloud::loadbalancer::vip_internal_ip { + $all_vip_array = $vip_public_ip_array + } + if ! $::cloud::loadbalancer::vip_public_ip and $::cloud::loadbalancer::vip_internal_ip { + $all_vip_array = $vip_internal_ip_array + } + if ! $::cloud::loadbalancer::vip_internal_ip and ! $::cloud::loadbalancer::vip_public_ip { + fail('vip_public_ip and vip_internal_ip are both set to false, no binding is possible.') + } + + # when we do not want binding + if ($ip == false) { + notice("no HAproxy binding for ${name} has been enabled.") + } else { + # when we want both internal & public binding + if ($ip == true) { + $listen_ip_real = $all_vip_array + } else { + # when binding is specified in parameter + if ($ip in $all_vip_array) { + $listen_ip_real = $ip + } else { + fail("${ip} is not part of VIP pools.") + } + } + cloud::loadbalancer::listen_http { $name : + ports => $port, + httpchk => $httpchk, + listen_ip => [$listen_ip_real]; + } + } + +} diff --git a/manifests/loadbalancer/listen_http.pp b/manifests/loadbalancer/listen_http.pp index 9d281d58..63bc0b8e 100644 --- a/manifests/loadbalancer/listen_http.pp +++ b/manifests/loadbalancer/listen_http.pp @@ -20,16 +20,19 @@ define cloud::loadbalancer::listen_http( $ports = 'unset', $httpchk = 'httpchk', + $options = {}, $listen_ip = '0.0.0.0') { + $options_basic = {'mode' => 'http', + 'balance' => 'roundrobin', + 'http-check' => 'expect ! rstatus ^5', + 'option' => ['tcpka', 'tcplog', $httpchk] } + + $options_custom = merge($options_basic, $options) + haproxy::listen { $name: ipaddress => $listen_ip, ports => $ports, - options => { - 'mode' => 'http', - 'balance' => 'roundrobin', - 'option' => ['tcpka', 'tcplog', $httpchk], - 'http-check' => 'expect ! rstatus ^5', - } + options => $options_custom, } } diff --git a/spec/classes/cloud_loadbalancer_spec.rb b/spec/classes/cloud_loadbalancer_spec.rb index 81c40e6e..ede4afb0 100644 --- a/spec/classes/cloud_loadbalancer_spec.rb +++ b/spec/classes/cloud_loadbalancer_spec.rb @@ -111,7 +111,7 @@ describe 'cloud::loadbalancer' do end end - context 'configure keepalived in backup' do + context 'when keepalived and HAproxy are in backup' do it 'configure vrrp_instance with BACKUP state' do should contain_keepalived__instance('1').with({ 'interface' => params[:keepalived_public_interface], @@ -123,6 +123,9 @@ describe 'cloud::loadbalancer' do 'notify_backup' => '"/etc/init.d/haproxy stop"', }) end # configure vrrp_instance with BACKUP state + it 'configure haproxy server without service managed' do + should contain_class('haproxy').with(:service_manage => false) + end # configure haproxy server end # configure keepalived in backup context 'configure keepalived in master' do @@ -139,6 +142,9 @@ describe 'cloud::loadbalancer' do 'notify_backup' => '"/etc/init.d/haproxy stop"', }) end + it 'configure haproxy server with service managed' do + should contain_class('haproxy').with(:service_manage => false) + end # configure haproxy server end # configure keepalived in master context 'configure logrotate file' do @@ -171,6 +177,64 @@ describe 'cloud::loadbalancer' do )} end # configure monitor haproxy listen + # test backward compatibility + context 'configure OpenStack binding on public network only' do + it { should contain_haproxy__listen('spice_cluster').with( + :ipaddress => [params[:vip_public_ip]], + :ports => '6082' + )} + end + + context 'configure OpenStack binding on both public and internal networks' do + before do + params.merge!( + :nova_api => true, + :galera_ip => '172.16.0.1', + :vip_public_ip => '172.16.0.1', + :vip_internal_ip => '192.168.0.1', + :keepalived_public_ipvs => ['172.16.0.1', '172.16.0.2'], + :keepalived_internal_ipvs => ['192.168.0.1', '192.168.0.2'] + ) + end + it { should contain_haproxy__listen('nova_api_cluster').with( + :ipaddress => ['172.16.0.1', '192.168.0.1'], + :ports => '8774' + )} + end + + context 'disable an OpenStack service binding' do + before do + params.merge!(:metadata_api => false) + end + it { should_not contain_haproxy__listen('metadata_api_cluster') } + end + + context 'should fail to configure OpenStack binding when vip_public_ip and vip_internal_ip are missing' do + before do + params.merge!( + :nova_api => true, + :galera_ip => '172.16.0.1', + :vip_public_ip => false, + :vip_internal_ip => false, + :keepalived_public_ipvs => ['172.16.0.1', '172.16.0.2'] + ) + end + it_raises 'a Puppet::Error', /vip_public_ip and vip_internal_ip are both set to false, no binding is possible./ + end + + context 'should fail to configure OpenStack binding when given VIP is not in the VIP pool list' do + before do + params.merge!( + :nova_api => '10.0.0.1', + :galera_ip => '172.16.0.1', + :vip_public_ip => '172.16.0.1', + :vip_internal_ip => false, + :keepalived_public_ipvs => ['172.16.0.1', '172.16.0.2'] + ) + end + it_raises 'a Puppet::Error', /10.0.0.1 is not part of VIP pools./ + end + context 'with a public OpenStack VIP not in the keepalived VIP list' do before do params.merge!( @@ -202,6 +266,7 @@ describe 'cloud::loadbalancer' do end it_raises 'a Puppet::Error', /galera_ip should be part of keepalived_public_ipvs or keepalived_internal_ipvs./ end + end # shared:: openstack loadbalancer context 'on Debian platforms' do