From 7b6b097d8ac8ebaf3058484ef0c3d5b464fbdc1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harald=20Jens=C3=A5s?= Date: Mon, 13 May 2019 19:20:05 +0200 Subject: [PATCH] Convert ipv6 netmask to prefix in dnsmasq.conf dnsmasq.conf require a prefix lenght as netmask for IPv6. Convert a IPv6 address netmask to prefix. Closes-Bug: #1828837 Change-Id: Idf84ba30eb4eb6d202faa470209f10c9da40e80b --- .../functions/ipv6_netmask_to_prefix.rb | 25 +++++++++++++++++++ manifests/inspector.pp | 2 ++ ...sq-conf-ipv6-netmask-6ff367f7c6ed5653.yaml | 6 +++++ spec/classes/ironic_inspector_spec.rb | 12 ++++++++- spec/functions/ipv6_netmask_to_prefix_spec.rb | 9 +++++++ templates/inspector_dnsmasq_http.erb | 2 +- templates/inspector_dnsmasq_tftp.erb | 2 +- 7 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 lib/puppet/functions/ipv6_netmask_to_prefix.rb create mode 100644 releasenotes/notes/fix-dnsmasq-conf-ipv6-netmask-6ff367f7c6ed5653.yaml create mode 100644 spec/functions/ipv6_netmask_to_prefix_spec.rb diff --git a/lib/puppet/functions/ipv6_netmask_to_prefix.rb b/lib/puppet/functions/ipv6_netmask_to_prefix.rb new file mode 100644 index 00000000..f0a93656 --- /dev/null +++ b/lib/puppet/functions/ipv6_netmask_to_prefix.rb @@ -0,0 +1,25 @@ +Puppet::Functions.create_function(:ipv6_netmask_to_prefix) do + def ipv6_netmask_to_prefix(args) + require 'ipaddr' + result = [] + args.each do |ip_subnet| + begin + if IPAddr.new(ip_subnet["netmask"]).ipv6? + # TODO(hjensas) Once we have ruby stdlib >= 2.5.x we can use + # IPAddr.new().prefix instead of counting 1's. + prefix = IPAddr.new(ip_subnet["netmask"]).to_i.to_s(2).count("1") + Puppet.debug("Netmask #{ip_subnet["netmask"]} changed to prefix #{prefix}") + ip_subnet_dup = ip_subnet.dup + ip_subnet_dup["netmask"] = prefix + result << ip_subnet_dup + else + result << ip_subnet + end + rescue IPAddr::AddressFamilyError, IPAddr::Error, IPAddr::InvalidAddressError, IPAddr::InvalidPrefixError => e + # Ignore it + result << ip_subnet + end + end + return result + end +end diff --git a/manifests/inspector.pp b/manifests/inspector.pp index 141b9405..c3433726 100644 --- a/manifests/inspector.pp +++ b/manifests/inspector.pp @@ -311,6 +311,8 @@ class ironic::inspector ( require => Anchor['ironic-inspector::config::begin'], } + $dnsmasq_ip_subnets_real = ipv6_netmask_to_prefix($dnsmasq_ip_subnets) + if $pxe_transfer_protocol == 'tftp' { file { '/etc/ironic-inspector/dnsmasq.conf': ensure => 'present', diff --git a/releasenotes/notes/fix-dnsmasq-conf-ipv6-netmask-6ff367f7c6ed5653.yaml b/releasenotes/notes/fix-dnsmasq-conf-ipv6-netmask-6ff367f7c6ed5653.yaml new file mode 100644 index 00000000..39033ae0 --- /dev/null +++ b/releasenotes/notes/fix-dnsmasq-conf-ipv6-netmask-6ff367f7c6ed5653.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + dnsmasq.conf require netmask for IPv6 to be a prefix. If IPv6 netmask is + used it will be converted to a prefix. See bug: `1828367 + `_ diff --git a/spec/classes/ironic_inspector_spec.rb b/spec/classes/ironic_inspector_spec.rb index 425d41e3..ebc6de0b 100644 --- a/spec/classes/ironic_inspector_spec.rb +++ b/spec/classes/ironic_inspector_spec.rb @@ -58,7 +58,11 @@ describe 'ironic::inspector' do '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'}]}], + '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, @@ -164,6 +168,12 @@ describe 'ironic::inspector' do 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( diff --git a/spec/functions/ipv6_netmask_to_prefix_spec.rb b/spec/functions/ipv6_netmask_to_prefix_spec.rb new file mode 100644 index 00000000..cf85794f --- /dev/null +++ b/spec/functions/ipv6_netmask_to_prefix_spec.rb @@ -0,0 +1,9 @@ +require 'spec_helper' + +describe 'ipv6_netmask_to_prefix' do + it { should run.with_params([{'ip_range' => '192.168.0.100,192.168.0.120'}]).and_return([{'ip_range' => '192.168.0.100,192.168.0.120'}])} + it { should run.with_params([{'netmask' => '255.255.255.0',}]).and_return([{'netmask' => '255.255.255.0'}])} + it { should run.with_params([{'netmask' => 'ffff:ffff:ffff:ffff::'}]).and_return([{'netmask' => 64}])} + it { should run.with_params([{'netmask' => '64'}]).and_return([{'netmask' => '64'}])} + it { should run.with_params([{'netmask' => 64}]).and_return([{'netmask' => 64}])} +end diff --git a/templates/inspector_dnsmasq_http.erb b/templates/inspector_dnsmasq_http.erb index 4c4ed8f4..6c891ae6 100644 --- a/templates/inspector_dnsmasq_http.erb +++ b/templates/inspector_dnsmasq_http.erb @@ -4,7 +4,7 @@ interface=<%= @dnsmasq_interface %> log-dhcp log-queries <% end %> -<% @dnsmasq_ip_subnets.each do |s| -%> +<% @dnsmasq_ip_subnets_real.each do |s| -%> <% if s['tag'] and s['netmask'] -%> dhcp-range=set:<%= s['tag'] -%>,<%= s['ip_range'] -%>,<%= s['netmask'] -%>,10m <% elsif s['tag'] -%> diff --git a/templates/inspector_dnsmasq_tftp.erb b/templates/inspector_dnsmasq_tftp.erb index a0ac56bb..cf0ec1c1 100644 --- a/templates/inspector_dnsmasq_tftp.erb +++ b/templates/inspector_dnsmasq_tftp.erb @@ -4,7 +4,7 @@ interface=<%= @dnsmasq_interface %> log-dhcp log-queries <% end %> -<% @dnsmasq_ip_subnets.each do |s| -%> +<% @dnsmasq_ip_subnets_real.each do |s| -%> <% if s['tag'] and s['netmask'] -%> dhcp-range=set:<%= s['tag'] -%>,<%= s['ip_range'] -%>,<%= s['netmask'] -%>,10m <% elsif s['tag'] -%>