Files
puppet-ironic/spec/classes/ironic_inspector_spec.rb
Harald Jensås 03550bc8c8 Add support to set option:mtu in inspector dnsmasq
It should be possible to configure the DHCP server to
provide the mtu option for inspection subnets.

This uses the dhcp-option-force so that the option is
provided also when the client does not ask for it.
According to dnsmasq manual page this is sometimes
required when sending options to PXELINUX.

Closes-Bug: #1845487
Change-Id: Ic95dbf1867fb5397f1b6d8f23466910a97051cb6
2019-09-26 13:49:56 +02:00

350 lines
17 KiB
Ruby

#
# Copyright (C) 2015 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 ironic::inspector class
#
require 'spec_helper'
describe 'ironic::inspector' do
let :pre_condition do
"class { 'ironic::inspector::authtoken':
password => 'password',
}"
end
let :params do
{ :package_ensure => 'present',
:enabled => true,
:pxe_transfer_protocol => 'tftp',
:auth_strategy => 'keystone',
:dnsmasq_interface => 'br-ctlplane',
:ramdisk_logs_dir => '/var/log/ironic-inspector/ramdisk/',
:add_ports => 'pxe',
:keep_ports => 'all',
:store_data => 'none',
:ironic_auth_type => 'password',
:ironic_username => 'ironic',
:ironic_tenant_name => 'services',
:ironic_auth_url => 'http://127.0.0.1:5000/v3',
:ironic_max_retries => 30,
:ironic_retry_interval => 2,
:swift_auth_type => 'password',
:swift_username => 'ironic',
:swift_tenant_name => 'services',
:swift_auth_url => 'http://127.0.0.1:5000/v3',
:dnsmasq_ip_subnets => [{ 'ip_range' =>
'192.168.0.100,192.168.0.120',
'mtu' => '1350'},
{ 'tag' => 'subnet1',
'ip_range' => '192.168.1.100,192.168.1.200',
'netmask' => '255.255.255.0',
'gateway' => '192.168.1.254',
'mtu' => '1350'},
{ 'tag' => 'subnet2',
'ip_range' => '192.168.2.100,192.168.2.200',
'netmask' => '255.255.255.0',
'gateway' => '192.168.2.254',
'classless_static_routes' => [{'destination' => '1.2.3.0/24',
'nexthop' => '192.168.2.1'},
{'destination' => '4.5.6.0/24',
'nexthop' => '192.168.2.1'}]},
{ 'tag' => 'subnet3',
'ip_range' => '2001:4888:a03:313a:c0:fe0:0:c200,2001:4888:a03:313a:c0:fe0:0:c2ff',
'netmask' => 'ffff:ffff:ffff:ffff::',
'gateway' => '2001:4888:a03:313a:c0:fe0:0:c000' }],
:dnsmasq_local_ip => '192.168.0.1',
:ipxe_timeout => 0,
:http_port => 8088,
:tftp_root => '/tftpboot',
:http_root => '/httpboot', }
end
shared_examples_for 'ironic inspector' do
let :p do
params
end
it { is_expected.to contain_class('ironic::params') }
it 'installs ironic inspector package' do
if platform_params.has_key?(:inspector_package)
is_expected.to contain_package('ironic-inspector').with(
:name => platform_params[:inspector_package],
:ensure => p[:package_ensure],
:tag => ['openstack', 'ironic-inspector-package'],
)
is_expected.to contain_package('ironic-inspector').that_requires('Anchor[ironic-inspector::install::begin]')
is_expected.to contain_package('ironic-inspector').that_notifies('Anchor[ironic-inspector::install::end]')
end
end
it 'ensure ironic inspector service is running' do
is_expected.to contain_service('ironic-inspector').with(
'hasstatus' => true,
'tag' => 'ironic-inspector-service',
)
end
it 'ensure ironic inspector dnsmasq service is running' do
is_expected.to contain_service('ironic-inspector-dnsmasq').with(
'hasstatus' => true,
'tag' => 'ironic-inspector-dnsmasq-service',
)
end
it 'configures inspector.conf' do
is_expected.to contain_ironic_inspector_config('DEFAULT/listen_address').with_value('<SERVICE DEFAULT>')
is_expected.to contain_ironic_inspector_config('DEFAULT/auth_strategy').with_value(p[:auth_strategy])
is_expected.to contain_ironic_inspector_config('DEFAULT/timeout').with_value('<SERVICE DEFAULT>')
is_expected.to contain_ironic_inspector_config('DEFAULT/transport_url').with_value('fake://')
is_expected.to contain_ironic_inspector_config('capabilities/boot_mode').with_value('<SERVICE DEFAULT>')
is_expected.to contain_ironic_inspector_config('iptables/dnsmasq_interface').with_value(p[:dnsmasq_interface])
is_expected.to contain_ironic_inspector_config('processing/ramdisk_logs_dir').with_value(p[:ramdisk_logs_dir])
is_expected.to contain_ironic_inspector_config('processing/always_store_ramdisk_logs').with_value('<SERVICE DEFAULT>')
is_expected.to contain_ironic_inspector_config('processing/add_ports').with_value(p[:add_ports])
is_expected.to contain_ironic_inspector_config('processing/keep_ports').with_value(p[:keep_ports])
is_expected.to contain_ironic_inspector_config('processing/store_data').with_value(p[:store_data])
is_expected.to contain_ironic_inspector_config('ironic/auth_type').with_value(p[:ironic_auth_type])
is_expected.to contain_ironic_inspector_config('ironic/username').with_value(p[:ironic_username])
is_expected.to contain_ironic_inspector_config('ironic/project_name').with_value(p[:ironic_tenant_name])
is_expected.to contain_ironic_inspector_config('ironic/project_domain_name').with_value('Default')
is_expected.to contain_ironic_inspector_config('ironic/user_domain_name').with_value('Default')
is_expected.to contain_ironic_inspector_config('ironic/auth_url').with_value(p[:ironic_auth_url])
is_expected.to contain_ironic_inspector_config('ironic/max_retries').with_value(p[:ironic_max_retries])
is_expected.to contain_ironic_inspector_config('ironic/retry_interval').with_value(p[:ironic_retry_interval])
is_expected.to contain_ironic_inspector_config('swift/auth_type').with_value(p[:swift_auth_type])
is_expected.to contain_ironic_inspector_config('swift/username').with_value(p[:swift_username])
is_expected.to contain_ironic_inspector_config('swift/project_name').with_value(p[:swift_tenant_name])
is_expected.to contain_ironic_inspector_config('swift/project_domain_name').with_value('Default')
is_expected.to contain_ironic_inspector_config('swift/user_domain_name').with_value('Default')
is_expected.to contain_ironic_inspector_config('swift/auth_url').with_value(p[:swift_auth_url])
is_expected.to contain_ironic_inspector_config('processing/processing_hooks').with_value('$default_processing_hooks')
is_expected.to contain_ironic_inspector_config('processing/node_not_found_hook').with_value('<SERVICE DEFAULT>')
is_expected.to contain_ironic_inspector_config('discovery/enroll_node_driver').with_value('<SERVICE DEFAULT>')
end
it 'should contain file /etc/ironic-inspector/inspector.conf' do
is_expected.to contain_file('/etc/ironic-inspector/inspector.conf').with(
'ensure' => 'present',
'owner' => 'ironic-inspector',
'group' => 'ironic-inspector',
'require' => 'Anchor[ironic-inspector::config::begin]',
)
end
it 'should contain file /etc/ironic-inspector/dnsmasq.conf' do
is_expected.to contain_file('/etc/ironic-inspector/dnsmasq.conf').with(
'ensure' => 'present',
'require' => 'Anchor[ironic-inspector::config::begin]',
'content' => /pxelinux/,
)
is_expected.to contain_file('/etc/ironic-inspector/dnsmasq.conf').with_content(
/dhcp-range=192.168.0.100,192.168.0.120,10m/
)
is_expected.to contain_file('/etc/ironic-inspector/dnsmasq.conf').with_content(
/dhcp-option-force=option:mtu,1350/
)
is_expected.to contain_file('/etc/ironic-inspector/dnsmasq.conf').with_content(
/dhcp-range=set:subnet1,192.168.1.100,192.168.1.200,255.255.255.0,10m/
)
is_expected.to contain_file('/etc/ironic-inspector/dnsmasq.conf').with_content(
/dhcp-option=tag:subnet1,option:router,192.168.1.254/
)
is_expected.to contain_file('/etc/ironic-inspector/dnsmasq.conf').with_content(
/dhcp-option-force=tag:subnet1,option:mtu,1350/
)
is_expected.to contain_file('/etc/ironic-inspector/dnsmasq.conf').with_content(
/dhcp-range=set:subnet2,192.168.2.100,192.168.2.200,255.255.255.0,10m/
)
is_expected.to contain_file('/etc/ironic-inspector/dnsmasq.conf').with_content(
/dhcp-option=tag:subnet2,option:router,192.168.2.254/
)
is_expected.to contain_file('/etc/ironic-inspector/dnsmasq.conf').with_content(
/dhcp-option=tag:subnet2,option:classless-static-route,1.2.3.0\/24,192.168.2.1,4.5.6.0\/24,192.168.2.1/
)
is_expected.to contain_file('/etc/ironic-inspector/dnsmasq.conf').with_content(
/dhcp-range=set:subnet3,2001:4888:a03:313a:c0:fe0:0:c200,2001:4888:a03:313a:c0:fe0:0:c2ff,64,10m/
)
is_expected.to contain_file('/etc/ironic-inspector/dnsmasq.conf').with_content(
/dhcp-option=tag:subnet3,option:router,2001:4888:a03:313a:c0:fe0:0:c000/
)
end
it 'should contain file /tftpboot/pxelinux.cfg/default' do
is_expected.to contain_file('/tftpboot/pxelinux.cfg/default').with(
'owner' => 'ironic-inspector',
'group' => 'ironic-inspector',
'seltype' => 'tftpdir_t',
'ensure' => 'present',
'require' => 'Anchor[ironic-inspector::config::begin]',
'content' => /default/,
)
is_expected.to contain_file('/tftpboot/pxelinux.cfg/default').with_content(
/initrd=agent.ramdisk ipa-inspection-callback-url=http:\/\/192.168.0.1:5050\/v1\/continue ipa-inspection-collectors=default/
)
end
context 'when overriding parameters' do
before :each do
params.merge!(
:dhcp_debug => true,
:listen_address => '127.0.0.1',
:ironic_password => 'password',
:ironic_project_domain_name => 'Default',
:ironic_user_domain_name => 'Default',
:ironic_auth_url => 'http://192.168.0.1:5000/v3',
:swift_password => 'password',
:swift_project_domain_name => 'Default',
:swift_user_domain_name => 'Default',
:swift_auth_url => 'http://192.168.0.1:5000/v3',
:pxe_transfer_protocol => 'http',
:additional_processing_hooks => 'hook1,hook2',
:ramdisk_kernel_args => 'foo=bar',
:http_port => 3816,
:tftp_root => '/var/lib/tftpboot',
:http_root => '/var/www/httpboot',
:detect_boot_mode => true,
:node_not_found_hook => 'enroll',
:discovery_default_driver => 'pxe_ipmitool',
:dnsmasq_ip_subnets => [{'ip_range' => '192.168.0.100,192.168.0.120'}],
:add_ports => 'all',
:always_store_ramdisk_logs => true,
)
end
it 'should replace default parameter with new value' do
is_expected.to contain_ironic_inspector_config('DEFAULT/listen_address').with_value(p[:listen_address])
is_expected.to contain_ironic_inspector_config('capabilities/boot_mode').with_value(p[:detect_boot_mode])
is_expected.to contain_ironic_inspector_config('ironic/password').with_value(p[:ironic_password]).with_secret(true)
is_expected.to contain_ironic_inspector_config('ironic/project_domain_name').with_value(p[:ironic_project_domain_name])
is_expected.to contain_ironic_inspector_config('ironic/user_domain_name').with_value(p[:ironic_user_domain_name])
is_expected.to contain_ironic_inspector_config('ironic/auth_url').with_value(p[:ironic_auth_url])
is_expected.to contain_ironic_inspector_config('swift/password').with_value(p[:swift_password]).with_secret(true)
is_expected.to contain_ironic_inspector_config('swift/project_domain_name').with_value(p[:swift_project_domain_name])
is_expected.to contain_ironic_inspector_config('swift/user_domain_name').with_value(p[:swift_user_domain_name])
is_expected.to contain_ironic_inspector_config('swift/auth_url').with_value(p[:swift_auth_url])
is_expected.to contain_ironic_inspector_config('processing/processing_hooks').with_value('$default_processing_hooks,hook1,hook2')
is_expected.to contain_ironic_inspector_config('processing/node_not_found_hook').with_value('enroll')
is_expected.to contain_ironic_inspector_config('processing/add_ports').with_value('all')
is_expected.to contain_ironic_inspector_config('discovery/enroll_node_driver').with_value('pxe_ipmitool')
is_expected.to contain_ironic_inspector_config('processing/always_store_ramdisk_logs').with_value(true)
end
it 'should contain file /etc/ironic-inspector/dnsmasq.conf' do
is_expected.to contain_file('/etc/ironic-inspector/dnsmasq.conf').with(
'ensure' => 'present',
'require' => 'Anchor[ironic-inspector::config::begin]',
'content' => /ipxe/,
)
is_expected.to contain_file('/etc/ironic-inspector/dnsmasq.conf').with_content(
/dhcp-boot=tag:ipxe,http:\/\/192.168.0.1:3816\/inspector.ipxe/
)
is_expected.to contain_file('/etc/ironic-inspector/dnsmasq.conf').with_content(
/dhcp-range=192.168.0.100,192.168.0.120,10m/
)
is_expected.to contain_file('/etc/ironic-inspector/dnsmasq.conf').with_content(
/log-dhcp/
)
is_expected.to contain_file('/etc/ironic-inspector/dnsmasq.conf').with_content(
/log-queries/
)
end
it 'should contain file /var/www/httpboot/inspector.ipxe' do
is_expected.to contain_file('/var/www/httpboot/inspector.ipxe').with(
'owner' => 'ironic-inspector',
'group' => 'ironic-inspector',
'seltype' => 'httpd_sys_content_t',
'ensure' => 'present',
'require' => 'Anchor[ironic-inspector::config::begin]',
'content' => /ipxe/,
)
is_expected.to contain_file('/var/www/httpboot/inspector.ipxe').with_content(
/kernel http:\/\/192.168.0.1:3816\/agent.kernel ipa-inspection-callback-url=http:\/\/192.168.0.1:5050\/v1\/continue ipa-inspection-collectors=default.* foo=bar || goto retry_boot/
)
end
context 'when ipxe_timeout is set' do
before :each do
params.merge!(
:ipxe_timeout => 30,
)
end
it 'should contain file /var/www/httpboot/inspector.ipxe' do
is_expected.to contain_file('/var/www/httpboot/inspector.ipxe').with_content(
/kernel --timeout 30000/)
end
end
end
context 'when enabling ppc64le support' do
let :pre_condition do
"class { 'ironic::inspector::authtoken': password => 'password', }
class { 'ironic::pxe': enable_ppc64le => true, }"
end
before do
params.merge!(
:enable_ppc64le => true,
)
end
it 'should contain file /etc/ironic-inspector/dnsmasq.conf' do
is_expected.to contain_file('/etc/ironic-inspector/dnsmasq.conf').with_content(
/dhcp-match=set:ppc64le,option:client-arch,14/)
end
it 'should contain file /tftpboot/ppc64le/default' do
is_expected.to contain_file('/tftpboot/ppc64le/default').with(
'owner' => 'ironic-inspector',
'group' => 'ironic-inspector',
'seltype' => 'tftpdir_t',
'ensure' => 'present',
'require' => 'Anchor[ironic-inspector::config::begin]',
'content' => /default/,
)
is_expected.to contain_file('/tftpboot/ppc64le/default').with_content(
/initrd=agent.ramdisk ipa-inspection-callback-url=http:\/\/192.168.0.1:5050\/v1\/continue ipa-inspection-collectors=default/
)
end
end
end
on_supported_os({
:supported_os => OSDefaults.get_supported_os
}).each do |os,facts|
context "on #{os}" do
let (:facts) do
facts.merge!(OSDefaults.get_facts({
:concat_basedir => '/var/lib/puppet/concat',
:fqdn => 'some.host.tld',
}))
end
let :platform_params do
case facts[:osfamily]
when 'Debian'
{ :inspector_package => 'ironic-inspector',
:inspector_service => 'ironic-inspector' }
when 'RedHat'
{ :inspector_service => 'ironic-inspector' }
end
end
it_behaves_like 'ironic inspector'
end
end
end