]> git.openstreetmap.org Git - chef.git/blobdiff - cookbooks/networking/recipes/default.rb
Work around lack of "onlink" route flag for IPv6 routes
[chef.git] / cookbooks / networking / recipes / default.rb
index 2c7ca3e01d39e4700572ef78a271b741159d290e..f56689d46d4929c49c6256b806ef97a293c4be44 100644 (file)
@@ -56,41 +56,45 @@ node[:networking][:interfaces].each do |name, interface|
     node.normal[:networking][:interfaces][name][:network] = IPAddr.new(interface[:address]).mask(prefix)
 
     if node[:networking][:netplan]
-      if interface[:interface] =~ /^(.*)\.(\d+)$/
-        deviceplan = netplan["network"]["vlans"][interface[:interface]] = {
-          "id" => Regexp.last_match(2).to_i,
-          "link" => Regexp.last_match(1),
-          "accept-ra" => false,
-          "addresses" => [],
-          "routes" => []
-        }
-      elsif interface[:bond]
-        deviceplan = netplan["network"]["bonds"][interface[:interface]] = {
-          "accept-ra" => false,
-          "addresses" => [],
-          "routes" => [],
-          "interfaces" => interface[:bond][:slaves].to_a,
-          "parameters" => {
-            "mode" => interface[:bond][:mode] || "active-backup",
-            "primary" => interface[:bond][:slaves].first,
-            "mii-monitor-interval" => interface[:bond][:miimon] || 100,
-            "down-delay" => interface[:bond][:downdelay] || 200,
-            "up-delay" => interface[:bond][:updelay] || 200
-          }
+      deviceplan = if interface[:interface] =~ /^(.*)\.(\d+)$/
+                     netplan["network"]["vlans"][interface[:interface]] ||= {
+                       "id" => Regexp.last_match(2).to_i,
+                       "link" => Regexp.last_match(1),
+                       "accept-ra" => false,
+                       "addresses" => [],
+                       "routes" => []
+                     }
+                   elsif interface[:interface] =~ /^bond\d+$/
+                     netplan["network"]["bonds"][interface[:interface]] ||= {
+                       "accept-ra" => false,
+                       "addresses" => [],
+                       "routes" => []
+                     }
+                   else
+                     netplan["network"]["ethernets"][interface[:interface]] ||= {
+                       "accept-ra" => false,
+                       "addresses" => [],
+                       "routes" => []
+                     }
+                   end
+
+      deviceplan["addresses"].push("#{interface[:address]}/#{prefix}")
+
+      if interface[:bond]
+        deviceplan["interfaces"] = interface[:bond][:slaves].to_a
+
+        deviceplan["parameters"] = {
+          "mode" => interface[:bond][:mode] || "active-backup",
+          "primary" => interface[:bond][:slaves].first,
+          "mii-monitor-interval" => interface[:bond][:miimon] || 100,
+          "down-delay" => interface[:bond][:downdelay] || 200,
+          "up-delay" => interface[:bond][:updelay] || 200
         }
 
         deviceplan["parameters"]["transmit-hash-policy"] = interface[:bond][:xmithashpolicy] if interface[:bond][:xmithashpolicy]
         deviceplan["parameters"]["lacp-rate"] = interface[:bond][:lacprate] if interface[:bond][:lacprate]
-      else
-        deviceplan = netplan["network"]["ethernets"][interface[:interface]] = {
-          "accept-ra" => false,
-          "addresses" => [],
-          "routes" => []
-        }
       end
 
-      deviceplan["addresses"].push("#{interface[:address]}/#{prefix}")
-
       if interface[:gateway]
         if interface[:family] == "inet"
           default_route = "0.0.0.0/0"
@@ -104,6 +108,21 @@ node[:networking][:interfaces].each do |name, interface|
           "metric" => interface[:metric],
           "on-link" => true
         )
+
+        # This ordering relies on systemd-networkd adding routes
+        # in reverse order and will need moving before the previous
+        # route once that is fixed:
+        #
+        # https://github.com/systemd/systemd/issues/5430
+        # https://github.com/systemd/systemd/pull/10938
+        if interface[:family] == "inet6" &&
+           !interface[:network].include?(interface[:gateway]) &&
+           !IPAddr.new("fe80::/64").include?(interface[:gateway])
+          deviceplan["routes"].push(
+            "to" => interface[:gateway],
+            "scope" => "link"
+          )
+        end
       end
     end
   else