Adds TLS support for OpenDaylight

Allows enabling TLS for the ODL service as well as OVS.

Partially-Implements: blueprint opendaylight-ssl-support

Depends-On: I719e8dddbd00d19fd8e1bd2a20dabd600b7b9d1c

Change-Id: Id579aea77bf8d679b514ef9851af36d9170e93a1
Signed-off-by: Tim Rozet <trozet@redhat.com>
This commit is contained in:
Tim Rozet 2018-01-03 15:04:49 -05:00
parent cd8dd6c0d7
commit 10468ae5f9
15 changed files with 700 additions and 42 deletions

View File

@ -0,0 +1,77 @@
# Copyright 2017 Red Hat, Inc.
#
# 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.
#
# == Class: tripleo::certmonger::opendaylight
#
# Request a certificate for the opendaylight service and do the necessary setup.
#
# === Parameters
#
# [*hostname*]
# The hostname of the node. this will be set in the CN of the certificate.
#
# [*service_certificate*]
# The path to the certificate that will be used for TLS in this service.
#
# [*service_key*]
# The path to the key that will be used for TLS in this service.
#
# [*certmonger_ca*]
# (Optional) The CA that certmonger will use to generate the certificates.
# Defaults to hiera('certmonger_ca', 'local').
#
# [*postsave_cmd*]
# (Optional) Specifies the command to execute after requesting a certificate.
# Defaults to 'if systemctl -q is-active opendaylight; then systemctl restart opendaylight; else true; fi'
#
# [*principal*]
# (Optional) The haproxy service principal that is set for opendaylight in kerberos.
# Defaults to undef
#
class tripleo::certmonger::opendaylight (
$hostname,
$service_certificate,
$service_key,
$certmonger_ca = hiera('certmonger_ca', 'local'),
$postsave_cmd = 'if systemctl -q is-active opendaylight; then systemctl restart opendaylight; else true; fi',
$principal = undef,
) {
include ::certmonger
certmonger_certificate { 'opendaylight' :
ensure => 'present',
certfile => $service_certificate,
keyfile => $service_key,
hostname => $hostname,
dnsname => $hostname,
principal => $principal,
postsave_cmd => $postsave_cmd,
ca => $certmonger_ca,
wait => true,
require => Class['::certmonger'],
}
file { $service_certificate :
owner => 'odl',
group => 'odl',
require => Certmonger_certificate['opendaylight']
}
file { $service_key :
owner => 'odl',
group => 'odl',
require => Certmonger_certificate['opendaylight']
}
File[$service_certificate] -> Odl_keystore<| title == 'controller' |>
File[$service_key] -> Odl_keystore<| title == 'controller' |>
}

View File

@ -0,0 +1,74 @@
# Copyright 2017 Red Hat, Inc.
#
# 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.
#
# == Class: tripleo::certmonger::openvswitch
#
# Request a certificate for the openvswitch service and do the necessary setup.
#
# === Parameters
#
# [*hostname*]
# The hostname of the node. this will be set in the CN of the certificate.
#
# [*service_certificate*]
# The path to the certificate that will be used for TLS in this service.
#
# [*service_key*]
# The path to the key that will be used for TLS in this service.
#
# [*certmonger_ca*]
# (Optional) The CA that certmonger will use to generate the certificates.
# Defaults to hiera('certmonger_ca', 'local').
#
# [*postsave_cmd*]
# (Optional) Specifies the command to execute after requesting a certificate.
# Defaults to "systemctl reload openvswitch"
#
# [*principal*]
# (Optional) The haproxy service principal that is set for openvswitch in kerberos.
# Defaults to undef
#
class tripleo::certmonger::openvswitch (
$hostname,
$service_certificate,
$service_key,
$certmonger_ca = hiera('certmonger_ca', 'local'),
$postsave_cmd = 'systemctl reload openvswitch',
$principal = undef,
) {
include ::certmonger
certmonger_certificate { 'openvswitch' :
ensure => 'present',
certfile => $service_certificate,
keyfile => $service_key,
hostname => $hostname,
dnsname => $hostname,
principal => $principal,
postsave_cmd => $postsave_cmd,
ca => $certmonger_ca,
wait => true,
require => Class['::certmonger'],
}
file { $service_certificate :
owner => 'openvswitch',
group => 'hugetlbfs',
require => Certmonger_certificate['openvswitch'],
}
file { $service_key :
owner => 'openvswitch',
group => 'hugetlbfs',
require => Certmonger_certificate['openvswitch'],
}
}

View File

@ -688,6 +688,7 @@ class tripleo::haproxy (
$nova_osapi_network = hiera('nova_api_network', undef),
$nova_placement_network = hiera('nova_placement_network', undef),
$octavia_network = hiera('octavia_api_network', undef),
$opendaylight_network = hiera('opendaylight_api_network', undef),
$panko_network = hiera('panko_api_network', undef),
$ovn_dbs_network = hiera('ovn_dbs_network', undef),
$ec2_api_network = hiera('ec2_api_network', undef),
@ -1489,23 +1490,27 @@ class tripleo::haproxy (
if $opendaylight {
::tripleo::haproxy::endpoint { 'opendaylight':
internal_ip => unique([hiera('opendaylight_api_vip', $controller_virtual_ip), $controller_virtual_ip]),
service_port => $ports[opendaylight_api_port],
ip_addresses => hiera('opendaylight_api_node_ips', $controller_hosts_real),
server_names => hiera('opendaylight_api_node_names', $controller_hosts_names_real),
mode => 'http',
listen_options => {
internal_ip => unique([hiera('opendaylight_api_vip', $controller_virtual_ip), $controller_virtual_ip]),
service_port => $ports[opendaylight_api_port],
ip_addresses => hiera('opendaylight_api_node_ips', $controller_hosts_real),
server_names => hiera('opendaylight_api_node_names', $controller_hosts_names_real),
mode => 'http',
member_options => union($haproxy_member_options, $internal_tls_member_options),
service_network => $opendaylight_network,
listen_options => {
'balance' => 'source',
},
}
::tripleo::haproxy::endpoint { 'opendaylight_ws':
internal_ip => unique([hiera('opendaylight_api_vip', $controller_virtual_ip), $controller_virtual_ip]),
service_port => $ports[opendaylight_ws_port],
ip_addresses => hiera('opendaylight_api_node_ips', $controller_hosts_real),
server_names => hiera('opendaylight_api_node_names', $controller_hosts_names_real),
mode => 'http',
listen_options => {
internal_ip => unique([hiera('opendaylight_api_vip', $controller_virtual_ip), $controller_virtual_ip]),
service_port => $ports[opendaylight_ws_port],
ip_addresses => hiera('opendaylight_api_node_ips', $controller_hosts_real),
server_names => hiera('opendaylight_api_node_names', $controller_hosts_names_real),
mode => 'http',
haproxy_listen_bind_param => [], # We don't use a transparent proxy (diverting non-destined haproxy traffic)
service_network => $opendaylight_network,
listen_options => {
# NOTE(jaosorior): Websockets have more overhead in establishing
# connections than regular HTTP connections. Also, since it begins
# as an HTTP connection and then "upgrades" to a TCP connection, some

View File

@ -83,6 +83,16 @@
# it will create.
# Defaults to hiera('tripleo::profile::base::etcd::certificate_specs', {}).
#
# [*odl_certificate_specs*]
# (Optional) The specifications to give to certmonger for the certificate(s)
# it will create.
# Defaults to hiera('tripleo::profile::base::odl::certificate_specs', {}).
#
# [*ovs_certificate_specs*]
# (Optional) The specifications to give to certmonger for the certificate(s)
# it will create.
# Defaults to hiera('tripleo::profile::base::ovs::certificate_specs', {}).
#
class tripleo::profile::base::certmonger_user (
$apache_certificates_specs = hiera('apache_certificates_specs', {}),
$apache_postsave_cmd = undef,
@ -94,6 +104,8 @@ class tripleo::profile::base::certmonger_user (
$mysql_certificate_specs = hiera('tripleo::profile::base::database::mysql::certificate_specs', {}),
$rabbitmq_certificate_specs = hiera('tripleo::profile::base::rabbitmq::certificate_specs', {}),
$etcd_certificate_specs = hiera('tripleo::profile::base::etcd::certificate_specs', {}),
$odl_certificate_specs = hiera('tripleo::profile::base::neutron::opendaylight::certificate_specs', {}),
$ovs_certificate_specs = hiera('tripleo::profile::base::neutron::plugins::ovs::opendaylight::certificate_specs', {}),
) {
unless empty($haproxy_certificates_specs) {
$reload_haproxy = ['systemctl reload haproxy']
@ -140,4 +152,10 @@ class tripleo::profile::base::certmonger_user (
unless empty($etcd_certificate_specs) {
ensure_resource('class', 'tripleo::certmonger::etcd', $etcd_certificate_specs)
}
unless empty($odl_certificate_specs) {
ensure_resource('class', 'tripleo::certmonger::opendaylight', $odl_certificate_specs)
}
unless empty($ovs_certificate_specs) {
ensure_resource('class', 'tripleo::certmonger::openvswitch', $ovs_certificate_specs)
}
}

View File

@ -26,15 +26,39 @@
# (Optional) List of OpenStack Controller IPs for ODL API
# Defaults to hiera('opendaylight_api_node_ips')
#
# [*node_name*]
# (Optional) The short hostname of node
# Defaults to hiera('bootstrap_nodeid')
# [*certificate_specs*]
# (Optional) The specifications to give to certmonger for the certificate
# it will create. Note that the certificate nickname must be 'etcd' in
# the case of this service.
# Example with hiera:
# tripleo::profile::base::etcd::certificate_specs:
# hostname: <overcloud controller fqdn>
# service_certificate: <service certificate path>
# service_key: <service key path>
# principal: "etcd/<overcloud controller fqdn>"
# Defaults to {}.
#
# [*enable_internal_tls*]
# (Optional) Whether TLS in the internal network is enabled or not.
# Defaults to hiera('enable_internal_tls', false)
#
class tripleo::profile::base::neutron::opendaylight (
$step = Integer(hiera('step')),
$odl_api_ips = hiera('opendaylight_api_node_ips'),
$step = Integer(hiera('step')),
$odl_api_ips = hiera('opendaylight_api_node_ips'),
$certificate_specs = {},
$enable_internal_tls = hiera('enable_internal_tls', false),
) {
validate_hash($certificate_specs)
if $enable_internal_tls {
$tls_certfile = $certificate_specs['service_certificate']
$tls_keyfile = $certificate_specs['service_key']
} else {
$tls_certfile = undef
$tls_keyfile = undef
}
if $step >= 1 {
validate_array($odl_api_ips)
if empty($odl_api_ips) {
@ -43,11 +67,18 @@ class tripleo::profile::base::neutron::opendaylight (
fail('2 node OpenDaylight deployments are unsupported. Use 1 or greater than 2')
} elsif size($odl_api_ips) > 2 {
class { '::opendaylight':
enable_ha => true,
ha_node_ips => $odl_api_ips,
enable_ha => true,
ha_node_ips => $odl_api_ips,
enable_tls => $enable_internal_tls,
tls_key_file => $tls_keyfile,
tls_cert_file => $tls_certfile
}
} else {
include ::opendaylight
class { '::opendaylight':
enable_tls => $enable_internal_tls,
tls_key_file => $tls_keyfile,
tls_cert_file => $tls_certfile
}
}
}
}

View File

@ -36,7 +36,15 @@
#
# [*conn_proto*]
# (Optional) Protocol to use to for ODL REST access
# Defaults to hiera('opendaylight::nb_connection_protocol')
# Defaults to 'http'
#
# [*enable_internal_tls*]
# (Optional) Whether TLS in the internal network is enabled or not.
# Defaults to hiera('enable_internal_tls', false)
#
# [*internal_api_fqdn*]
# (Optional) FQDN.
# Defaults to hiera('cloud_name_internal_api')
#
# [*step*]
# (Optional) The current step in deployment. See tripleo-heat-templates
@ -44,21 +52,28 @@
# Defaults to hiera('step')
#
class tripleo::profile::base::neutron::plugins::ml2::opendaylight (
$odl_port = hiera('opendaylight::odl_rest_port'),
$odl_username = hiera('opendaylight::username'),
$odl_password = hiera('opendaylight::password'),
$odl_url_ip = hiera('opendaylight_api_vip'),
$conn_proto = hiera('opendaylight::nb_connection_protocol'),
$step = Integer(hiera('step')),
$odl_port = hiera('opendaylight::odl_rest_port'),
$odl_username = hiera('opendaylight::username'),
$odl_password = hiera('opendaylight::password'),
$odl_url_ip = hiera('opendaylight_api_vip'),
$conn_proto = 'http',
$enable_internal_tls = hiera('enable_internal_tls', false),
$internal_api_fqdn = hiera('cloud_name_internal_api'),
$step = Integer(hiera('step')),
) {
if $step >= 4 {
if ! $odl_url_ip { fail('OpenDaylight API VIP is Empty') }
if $enable_internal_tls {
if empty($internal_api_fqdn) { fail('Internal API FQDN is Empty') }
$odl_url_addr = $internal_api_fqdn
} else {
if empty($odl_url_ip) { fail('OpenDaylight API VIP is Empty') }
$odl_url_addr = $odl_url_ip
}
class { '::neutron::plugins::ml2::opendaylight':
odl_username => $odl_username,
odl_password => $odl_password,
odl_url => "${conn_proto}://${odl_url_ip}:${odl_port}/controller/nb/v2/neutron",
odl_url => "${conn_proto}://${odl_url_addr}:${odl_port}/controller/nb/v2/neutron",
}
}
}

View File

@ -36,7 +36,27 @@
#
# [*conn_proto*]
# (Optional) Protocol to use to for ODL REST access
# Defaults to hiera('opendaylight::nb_connection_protocol')
# Defaults to 'http'
#
# [*certificate_specs*]
# (Optional) The specifications to give to certmonger for the certificate
# it will create. Note that the certificate nickname must be 'etcd' in
# the case of this service.
# Example with hiera:
# tripleo::profile::base::etcd::certificate_specs:
# hostname: <overcloud controller fqdn>
# service_certificate: <service certificate path>
# service_key: <service key path>
# principal: "etcd/<overcloud controller fqdn>"
# Defaults to {}.
#
# [*enable_internal_tls*]
# (Optional) Whether TLS in the internal network is enabled or not.
# Defaults to hiera('enable_internal_tls', false)
#
# [*tunnel_ip*]
# (Optional) IP to use for Tenant VXLAN/GRE tunneling source address
# Defaults to hiera('neutron::agents::ml2::ovs::local_ip')
#
# [*step*]
# (Optional) The current step in deployment. See tripleo-heat-templates
@ -44,28 +64,43 @@
# Defaults to hiera('step')
#
class tripleo::profile::base::neutron::plugins::ovs::opendaylight (
$odl_port = hiera('opendaylight::odl_rest_port'),
$odl_check_url = hiera('opendaylight_check_url'),
$odl_api_ips = hiera('opendaylight_api_node_ips'),
$odl_url_ip = hiera('opendaylight_api_vip'),
$conn_proto = hiera('opendaylight::nb_connection_protocol'),
$step = Integer(hiera('step')),
$odl_port = hiera('opendaylight::odl_rest_port'),
$odl_check_url = hiera('opendaylight_check_url'),
$odl_api_ips = hiera('opendaylight_api_node_ips'),
$odl_url_ip = hiera('opendaylight_api_vip'),
$conn_proto = 'http',
$certificate_specs = {},
$enable_internal_tls = hiera('enable_internal_tls', false),
$tunnel_ip = hiera('neutron::agents::ml2::ovs::local_ip'),
$step = Integer(hiera('step')),
) {
if $step >= 4 {
if empty($odl_api_ips) { fail('No IPs assigned to OpenDaylight Api Service') }
if ! $odl_url_ip { fail('OpenDaylight API VIP is Empty') }
if empty($odl_api_ips) { fail('No IPs assigned to OpenDaylight API Service') }
if empty($odl_url_ip) { fail('OpenDaylight API VIP is Empty') }
# Build URL to check if ODL is up before connecting OVS
$opendaylight_url = "${conn_proto}://${odl_url_ip}:${odl_port}/${odl_check_url}"
$odl_ovsdb_str = join(regsubst($odl_api_ips, '.+', 'tcp:\0:6640'), ' ')
if $enable_internal_tls {
$tls_certfile = $certificate_specs['service_certificate']
$tls_keyfile = $certificate_specs['service_key']
$odl_ovsdb_str = join(regsubst($odl_api_ips, '.+', 'ssl:\0:6640'), ' ')
} else {
$tls_certfile = undef
$tls_keyfile = undef
$odl_ovsdb_str = join(regsubst($odl_api_ips, '.+', 'tcp:\0:6640'), ' ')
}
class { '::neutron::plugins::ovs::opendaylight':
tunnel_ip => hiera('neutron::agents::ml2::ovs::local_ip'),
tunnel_ip => $tunnel_ip,
odl_check_url => $opendaylight_url,
odl_ovsdb_iface => $odl_ovsdb_str,
enable_tls => $enable_internal_tls,
tls_key_file => $tls_keyfile,
tls_cert_file => $tls_certfile
}
}
}

View File

@ -0,0 +1,5 @@
---
features:
- |
Adds support for deploying OpenDaylight with TLS. Open vSwitch is also
configured with TLS in this deployment.

View File

@ -0,0 +1,71 @@
#
# Copyright (C) 2017 Red Hat Inc.
#
# 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.
#
# Unit tests for tripleo
#
require 'spec_helper'
describe 'tripleo::certmonger::opendaylight' do
let :params do
{ :hostname => 'localhost',
:service_certificate => '/etc/pki/tls/certs/odl.crt',
:service_key => '/etc/pki/tls/private/odl.key',
}
end
shared_examples_for 'tripleo::certmonger::opendaylight' do
before :each do
facts.merge!({ :step => 1 })
end
it 'should include the base for using certmonger' do
is_expected.to contain_class('certmonger')
end
it 'should request a certificate' do
is_expected.to contain_certmonger_certificate('opendaylight').with(
:ensure => 'present',
:certfile => params[:service_certificate],
:keyfile => params[:service_key],
:hostname => 'localhost',
:dnsname => 'localhost',
:ca => 'local',
:wait => true,
)
is_expected.to contain_file(params[:service_certificate]).with(
:owner => 'odl',
:group => 'odl',
:require => 'Certmonger_certificate[opendaylight]'
)
is_expected.to contain_file(params[:service_key]).with(
:owner => 'odl',
:group => 'odl',
:require => 'Certmonger_certificate[opendaylight]'
)
end
end
on_supported_os.each do |os, facts|
context "on #{os}" do
let(:facts) do
facts.merge({})
end
it_behaves_like 'tripleo::certmonger::opendaylight'
end
end
end

View File

@ -0,0 +1,68 @@
#
# Copyright (C) 2017 Red Hat Inc.
#
# 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.
#
# Unit tests for tripleo
#
require 'spec_helper'
describe 'tripleo::certmonger::openvswitch' do
shared_examples_for 'tripleo::certmonger::openvswitch' do
let :params do
{
:hostname => 'localhost',
:service_certificate => '/etc/pki/cert.crt',
:service_key => '/etc/pki/key.pem',
}
end
it 'should include the base for using certmonger' do
is_expected.to contain_class('certmonger')
end
it 'should request a certificate' do
is_expected.to contain_certmonger_certificate('openvswitch').with(
:ensure => 'present',
:certfile => '/etc/pki/cert.crt',
:keyfile => '/etc/pki/key.pem',
:hostname => 'localhost',
:dnsname => 'localhost',
:ca => 'local',
:wait => true,
)
is_expected.to contain_file('/etc/pki/cert.crt').with(
:owner => 'openvswitch',
:group => 'hugetlbfs',
:require => 'Certmonger_certificate[openvswitch]'
)
is_expected.to contain_file('/etc/pki/key.pem').with(
:owner => 'openvswitch',
:group => 'hugetlbfs',
:require => 'Certmonger_certificate[openvswitch]'
)
end
end
on_supported_os.each do |os, facts|
context "on #{os}" do
let(:facts) do
facts.merge({})
end
it_behaves_like 'tripleo::certmonger::openvswitch'
end
end
end

View File

@ -0,0 +1,97 @@
#
# Copyright (C) 2018 Red Hat, Inc.
#
# 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.
#
require 'spec_helper'
describe 'tripleo::profile::base::neutron::plugins::ml2::opendaylight' do
let :params do
{ :step => 4,
:odl_port => 8081,
:odl_username => 'dummy',
:odl_password => 'dummy'
}
end
shared_examples_for 'tripleo::profile::base::neutron::plugins::ml2::opendaylight' do
before :each do
facts.merge!({ :step => params[:step] })
end
context 'with no TLS and API IP empty' do
before do
params.merge!({
:odl_url_ip => '',
:internal_api_fqdn => [],
})
end
it_raises 'a Puppet::Error',/OpenDaylight API VIP is Empty/
end
context 'with no TLS' do
before do
params.merge!({
:odl_url_ip => '192.168.24.2',
:internal_api_fqdn => [],
})
end
it 'should configure ML2' do
is_expected.to contain_class('neutron::plugins::ml2::opendaylight').with(
:odl_username => params[:odl_username],
:odl_password => params[:odl_password],
:odl_url => "http://#{params[:odl_url_ip]}:#{params[:odl_port]}/controller/nb/v2/neutron"
)
end
end
context 'with TLS and FQDN empty' do
before do
params.merge!({
:enable_internal_tls => true,
:internal_api_fqdn => [],
:odl_url_ip => '192.168.24.2'
})
end
it_raises 'a Puppet::Error',/Internal API FQDN is Empty/
end
context 'with TLS' do
before do
params.merge!({
:enable_internal_tls => true,
:conn_proto => 'https',
:internal_api_fqdn => 'example.cloud.org',
:odl_url_ip => '192.168.24.2'
})
end
it 'should configure ML2' do
is_expected.to contain_class('neutron::plugins::ml2::opendaylight').with(
:odl_username => params[:odl_username],
:odl_password => params[:odl_password],
:odl_url => "https://#{params[:internal_api_fqdn]}:#{params[:odl_port]}/controller/nb/v2/neutron"
)
end
end
end
on_supported_os.each do |os, facts|
context "on #{os}" do
let(:facts) do
facts.merge({ :hostname => 'node.example.com' })
end
it_behaves_like 'tripleo::profile::base::neutron::plugins::ml2::opendaylight'
end
end
end

View File

@ -67,6 +67,46 @@ describe 'tripleo::profile::base::neutron::opendaylight' do
end
it 'should install and configure OpenDaylight in HA' do
is_expected.to contain_class('opendaylight').with(
:enable_ha => true,
:ha_node_ips => params[:odl_api_ips],
:enable_tls => false
)
end
end
context 'with TLS enabled' do
before do
params.merge!({
:enable_internal_tls => true,
:certificate_specs => {
"service_certificate" => "/etc/pki/tls/certs/odl.crt",
"service_key" => "/etc/pki/tls/private/odl.key"}
})
end
it 'should and configure OpenDaylight with TLS' do
is_expected.to contain_class('opendaylight').with(
:enable_tls => true,
:tls_key_file => params[:certificate_specs]['service_key'],
:tls_cert_file => params[:certificate_specs]['service_certificate']
)
end
end
context 'with TLS and HA enabled' do
before do
params.merge!({
:enable_internal_tls => true,
:certificate_specs => {
"service_certificate" => "/etc/pki/tls/certs/odl.crt",
"service_key" => "/etc/pki/tls/private/odl.key"},
:odl_api_ips => ['192.0.2.5', '192.0.2.6', '192.0.2.7']
})
end
it 'should and configure OpenDaylight with TLS and HA' do
is_expected.to contain_class('opendaylight').with(
:enable_tls => true,
:tls_key_file => params[:certificate_specs]['service_key'],
:tls_cert_file => params[:certificate_specs]['service_certificate'],
:enable_ha => true,
:ha_node_ips => params[:odl_api_ips]
)

View File

@ -0,0 +1,118 @@
#
# Copyright (C) 2018 Red Hat, Inc.
#
# 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.
#
require 'spec_helper'
describe 'tripleo::profile::base::neutron::plugins::ovs::opendaylight' do
let :params do
{ :step => 4,
:odl_port => 8081,
:odl_check_url => 'restconf/operational/network-topology:network-topology/topology/netvirt:1'
}
end
shared_examples_for 'tripleo::profile::base::neutron::plugins::ovs::opendaylight' do
before :each do
facts.merge!({ :step => params[:step] })
end
context 'with empty OpenDaylight API IPs' do
before do
params.merge!({
:odl_api_ips => [],
:tunnel_ip => '11.0.0.5',
:odl_url_ip => '192.0.2.6',
:odl_port => 8081
})
end
it 'should fail to configure OVS' do
is_expected.to compile.and_raise_error(/No IPs assigned to OpenDaylight API Service/)
end
end
context 'with empty OpenDaylight VIP' do
before do
params.merge!({
:odl_api_ips => ['192.0.2.5'],
:odl_url_ip => [],
:tunnel_ip => '11.0.0.5',
:odl_port => 8081
})
end
it 'should fail to configure OVS' do
is_expected.to compile.and_raise_error(/OpenDaylight API VIP is Empty/)
end
end
context 'with no TLS' do
before do
params.merge!({
:odl_api_ips => ['192.0.2.5'],
:odl_url_ip => '192.0.2.6',
:tunnel_ip => '11.0.0.5',
:odl_port => 8081
})
end
it 'should configure OVS for ODL' do
is_expected.to contain_class('neutron::plugins::ovs::opendaylight').with(
:tunnel_ip => params[:tunnel_ip],
:odl_check_url => "http://#{params[:odl_url_ip]}:#{params[:odl_port]}/#{params[:odl_check_url]}",
:odl_ovsdb_iface => "tcp:#{params[:odl_api_ips][0]}:6640",
:enable_tls => false,
:tls_key_file => nil,
:tls_cert_file => nil
)
end
end
context 'with TLS enabled' do
before do
File.stubs(:file?).returns(true)
File.stubs(:readlines).returns(["MIIFGjCCBAKgAwIBAgICA"])
params.merge!({
:odl_api_ips => ['192.0.2.5'],
:odl_url_ip => '192.0.2.6',
:tunnel_ip => '11.0.0.5',
:enable_internal_tls => true,
:conn_proto => 'https',
:odl_port => 8081,
:certificate_specs => {
"service_certificate" => "/etc/pki/tls/certs/ovs.crt",
"service_key" => "/etc/pki/tls/private/ovs.key"}
})
end
it 'should configure OVS for ODL' do
is_expected.to contain_class('neutron::plugins::ovs::opendaylight').with(
:tunnel_ip => params[:tunnel_ip],
:odl_check_url => "https://#{params[:odl_url_ip]}:#{params[:odl_port]}/#{params[:odl_check_url]}",
:odl_ovsdb_iface => "ssl:#{params[:odl_api_ips][0]}:6640",
:enable_tls => true,
:tls_key_file => params[:certificate_specs]['service_key'],
:tls_cert_file => params[:certificate_specs]['service_certificate']
)
end
end
end
on_supported_os.each do |os, facts|
context "on #{os}" do
let(:facts) do
facts.merge({ :hostname => 'node.example.com' })
end
it_behaves_like 'tripleo::profile::base::neutron::plugins::ovs::opendaylight'
end
end
end

View File

@ -1,2 +1,5 @@
---
step: 1
opendaylight_api_node_ips:
- '192.0.2.5'
opendaylight::tls_keystore_password: 'password'

View File

@ -25,4 +25,5 @@ fluentd::plugin_provider: "yum"
fluentd::repo_install: false
fluentd::service_name: "fluentd"
fluentd::service_provider: "systemd"
neutron::plugins::ovs::opendaylight::odl_username: 'admin'
neutron::plugins::ovs::opendaylight::odl_password: 'admin'