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

Reply via email to