BBlack has uploaded a new change for review. https://gerrit.wikimedia.org/r/203069
Change subject: add_ip6_mapped: middle approach ...................................................................... add_ip6_mapped: middle approach WIP - poorly factored, just functional POC for discussion This is the middle option inbetween "Disable prefix adverts on the routers" and the "ip token" approach... This uses rdisc6 to set the network portion of the up-command for the fixed address (so we're still reliant on RA there, but not on kernel-level autoconf). This has to be done through a ruby subscript (python's ipaddr module lacks necessary features) that executes locally on the host. On the autoconf front, it disables accept_ra_pinfo for the configured interface as a pre-up within /e/n/i (should be all that's needed on fresh boot), and again through sysctl (to get it applied for the first time when the host is already booted), and flushes existing dynamic addrs when first adding the pre-up to /e/n/i (as a once-only trigger), *after* the sysctl has also been applied. Change-Id: I4d87322704887ff20452b7b4c35b6ef9775dbeb9 --- A modules/interface/files/get_v6_mapped.rb M modules/interface/manifests/add_ip6_mapped.pp 2 files changed, 86 insertions(+), 32 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/operations/puppet refs/changes/69/203069/1 diff --git a/modules/interface/files/get_v6_mapped.rb b/modules/interface/files/get_v6_mapped.rb new file mode 100644 index 0000000..d89ac0d --- /dev/null +++ b/modules/interface/files/get_v6_mapped.rb @@ -0,0 +1,18 @@ +#!/usr/bin/ruby + +require 'ipaddr'; + +if ARGV.length != 2 + raise "Requires two arguments: interface and host address (lower 64 bits)" +end + +intf = ARGV[0]; +host = ARGV[1]; + +rd_cmd = "/bin/rdisc6 -1nq #{intf}"; +network = `#{rd_cmd}`; +if $?.exitstatus != 0 + raise "Command '#{rd_cmd}' failed" +end + +print (IPAddr.new(network) | IPAddr.new(host)).to_s() + "\n" diff --git a/modules/interface/manifests/add_ip6_mapped.pp b/modules/interface/manifests/add_ip6_mapped.pp index b4b8c79..ce90916 100644 --- a/modules/interface/manifests/add_ip6_mapped.pp +++ b/modules/interface/manifests/add_ip6_mapped.pp @@ -21,48 +21,84 @@ # $v6_mapped_lower64 looks like '::10:0:2:1' for a v4 of '10.0.2.1' $v6_mapped_lower64 = regsubst($ip4_address, '\.', ':', 'G') - $ipv6_address = inline_template("<%= require 'ipaddr'; (IPAddr.new(scope.lookupvar(\"::ipaddress6_${intf}\")).mask(64) | IPAddr.new(v6_mapped_lower64)).to_s() %>") - interface::ip { $title: - interface => $intf, - address => $ipv6_address, - prefixlen => '64' - } - # XXX Temporary: testing on cp1008 first in a couple of different scenarios... if $::hostname == 'cp1008' { - # The above sets up an "up" command to add the fixed IPv6 mapping of the v4 - # address statically, and also executes the command to add the address - # in the present if not configured. - # - # Below sets "ip token" to the same on distros that support it. The - # token command explicitly configures the lower 64 bits that will be - # used with any autoconf address, as opposed to one derived from the - # macaddr. This aligns the autoconf-assigned address with the fixed - # one set above, and can do so as a pre-up command to avoid ever - # having another address even temporarily. We could probably rely on - # this exclusively and drop the static address above, but the - # redundancy doesn't hurt (the autoconf simply won't end up appearing - # on the list at all when it duplicates the static address), and this - # allays any fears about relying on router advertisments. As above, - # this also executes itself in the present when first configured. + ############ + # Set address without relying on kernel autoconf (but still using RA prefix from network)... + ############ - if os_version('debian >= jessie || ubuntu >= trusty') { - $v6_token_cmd = "/sbin/ip token set $v6_mapped_lower64 dev ${intf}" - $v6_token_check_cmd = "/sbin/ip token get dev $intf | grep -qw $v6_mapped_lower64" - $v6_token_preup_cmd = "set iface[. = '${intf}']/pre-up '${v6_token_cmd}'" + # This provides the "rdisc6" command + package { 'ndisc6': ensure => present } - augeas { "${intf}_v6_token": + # Takes args like "eth0 ::1:2:3:4", uses rdisc6 to get network prefix + # and combines the two into a whole output address + file { '/usr/local/sbin/get_v6_mapped': + owner => 'root', + group => 'root', + mode => '0555', + source => 'puppet:///modules/interface/get_v6_mapped.rb', + require => Package['ndisc6'], + } + + $get_addr_cmd = "/usr/local/sbin/get_v6_mapped ${intf} ${v6_mapped_lower64}" + $ipaddr_cmd = "ip addr add $(${get_addr_cmd}) dev ${intf}" + + # Use augeas to add an 'up' command to the interface + augeas { "${intf}_ip6_mapped": + context => "/files/etc/network/interfaces/*[. = '${interface}' and ./family = 'inet']", + changes => "set up[last()+1] '${ipaddr_cmd}'", + onlyif => "match up[. = '${ipaddr_cmd}'] size == 0", + require => File['/usr/local/sbin/get_v6_mapped'], + } + + # Add the IP address manually as well when above first added + exec { "${intf}_ip6_mapped": + command => $ipaddr_cmd, + refreshonly => true, + subscribe => Augeas["${intf}_ip6_mapped"], + } + + ############ + # Deal with disabling autoconf... + ############ + + # This sets a pre-up command to disable accepting prefixes, which + # should disable the creation of macaddr-based autoconf addresses + # (on fresh boots when this is already set in the file...) + $v6_no_pinfo_cmd = "echo 0 >/proc/sys/net/ipv6/conf/${intf}/accept_ra_pinfo" + $v6_no_pinfo_preup_cmd = "set iface[. = '${intf}']/pre-up '${v6_no_pinfo_cmd}'" + augeas { "${intf}_v6_no_pinfo": context => '/files/etc/network/interfaces/', - changes => $v6_token_preup_cmd, + changes => $v6_no_pinfo_preup_cmd, } - exec { "${intf}_v6_token": - command => $v6_token_cmd, - unless => $v6_token_check_cmd, + # This sets it as a sysctl as well, which has the side effect of + # getting the parameter applied immediately for hosts that are + # already booted (so they'll stop accepting new prefixes, but + # still have a lingering autoconf address expiring slowly) + sysctl::parameters { "${intf}_v6_no_pinfo": + values => { "net.ipv6.conf.${inft}.accept_ra_pinfo" => 0 } } - } + + # This flushes the lingering address left behind above, IFF augeas + # took action (we didn't have these settings before this run), and + # after the sysctl above has run to suppress further updates. + exec { "${intf}_v6_flush_dynamic": + command => "/sbin/ip -6 addr flush dev ${intf} dynamic", + refreshonly => true, + subscribe => Augeas["${intf}_v6_no_pinfo"], + require => Exec['update_sysctl'], + } } # XXX end cp1008 testing block + else { + $ipv6_address = inline_template("<%= require 'ipaddr'; (IPAddr.new(scope.lookupvar(\"::ipaddress6_${intf}\")).mask(64) | IPAddr.new(v6_mapped_lower64)).to_s() %>") + interface::ip { $title: + interface => $intf, + address => $ipv6_address, + prefixlen => '64' + } + } } } -- To view, visit https://gerrit.wikimedia.org/r/203069 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I4d87322704887ff20452b7b4c35b6ef9775dbeb9 Gerrit-PatchSet: 1 Gerrit-Project: operations/puppet Gerrit-Branch: production Gerrit-Owner: BBlack <bbl...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits