github.com/coreos/mantle@v0.13.0/kola/tests/flannel/flannel.go (about)

     1  // Copyright 2015 CoreOS, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // flannel tests. tests assume flannel is using the 10.254.0.0/16 network.
    16  // these tests should really assert no units failed during boot (such as flanneld)
    17  // it is also unfortunate that we must retry, but starting
    18  // early-docker -> flanneld -> docker ->docker0 may not be ready by the time we ssh in.
    19  package flannel
    20  
    21  import (
    22  	"fmt"
    23  	"net"
    24  
    25  	"github.com/coreos/mantle/kola/cluster"
    26  	"github.com/coreos/mantle/kola/register"
    27  	"github.com/coreos/mantle/kola/tests/etcd"
    28  	"github.com/coreos/mantle/platform"
    29  	"github.com/coreos/mantle/platform/conf"
    30  )
    31  
    32  var (
    33  	flannelConf = conf.ContainerLinuxConfig(`etcd:
    34    discovery:                   $discovery
    35    listen_client_urls:          http://0.0.0.0:2379
    36    advertise_client_urls:       http://{PRIVATE_IPV4}:2379
    37    initial_advertise_peer_urls: http://{PRIVATE_IPV4}:2380
    38    listen_peer_urls:            http://{PRIVATE_IPV4}:2380
    39  systemd:
    40    units:
    41      - name: flannel-docker-opts.service
    42        dropins:
    43          - name: retry.conf
    44            contents: |
    45              [Service]
    46              TimeoutStartSec=300
    47              ExecStart=
    48              ExecStart=/bin/sh -exc 'for try in 1 2 3 4 5 6 ; do /usr/lib/coreos/flannel-wrapper -d /run/flannel/flannel_docker_opts.env -i && break  || sleep 10 ; try=fail ; done ; [ $try != fail ]'
    49      - name: docker.service
    50        enabled: true
    51      - name: flanneld.service
    52        enabled: true
    53        dropins:
    54          - name: 50-network-config.conf
    55            contents: |
    56              [Service]
    57              ExecStartPre=/usr/bin/etcdctl set /coreos.com/network/config '{ \"Network\": \"10.254.0.0/16\", \"Backend\": {\"Type\": \"$type\"} }'`)
    58  )
    59  
    60  func init() {
    61  	register.Register(&register.Test{
    62  		Run:         udp,
    63  		ClusterSize: 3,
    64  		Name:        "cl.flannel.udp",
    65  		Flags:       []register.Flag{register.RequiresInternetAccess}, // requires networking between nodes
    66  		Distros:     []string{"cl"},
    67  		UserData:    flannelConf.Subst("$type", "udp"),
    68  	})
    69  
    70  	register.Register(&register.Test{
    71  		Run:         vxlan,
    72  		ClusterSize: 3,
    73  		Name:        "cl.flannel.vxlan",
    74  		Flags:       []register.Flag{register.RequiresInternetAccess}, // requires networking between nodes
    75  		Distros:     []string{"cl"},
    76  		UserData:    flannelConf.Subst("$type", "vxlan"),
    77  	})
    78  }
    79  
    80  // get docker bridge ip from a machine
    81  func mach2bip(c cluster.TestCluster, m platform.Machine, ifname string) (string, error) {
    82  	// note the escaped % in awk.
    83  	out, err := c.SSH(m, fmt.Sprintf(`/usr/lib/systemd/systemd-networkd-wait-online --interface=%s --timeout=60 ; ip -4 -o addr show dev %s primary | awk -F " +|/" '{printf "%%s", $4}'`, ifname, ifname))
    84  	if err != nil {
    85  		return "", err
    86  	}
    87  
    88  	// XXX(mischief): unfortunately `ip` does not return a nonzero status if the interface doesn't exist.
    89  	if len(out) == 0 {
    90  		return "", fmt.Errorf("interface %q doesn't exist?", ifname)
    91  	}
    92  
    93  	return string(out), nil
    94  }
    95  
    96  // ping sends icmp packets from machine a to b using the ping tool.
    97  func ping(c cluster.TestCluster, a, b platform.Machine, ifname string) {
    98  	srcip, err := mach2bip(c, a, ifname)
    99  	if err != nil {
   100  		c.Fatalf("failed to get docker bridge ip #1: %v", err)
   101  	}
   102  
   103  	dstip, err := mach2bip(c, b, ifname)
   104  	if err != nil {
   105  		c.Fatalf("failed to get docker bridge ip #2: %v", err)
   106  	}
   107  
   108  	// ensure the docker bridges have the right network
   109  	_, ipnet, _ := net.ParseCIDR("10.254.0.0/16")
   110  	if !ipnet.Contains(net.ParseIP(srcip)) || !ipnet.Contains(net.ParseIP(dstip)) {
   111  		c.Fatalf("bridge ips (%s %s) not in flannel network (%s)", srcip, dstip, ipnet)
   112  	}
   113  
   114  	c.Logf("ping from %s(%s) to %s(%s)", a.ID(), srcip, b.ID(), dstip)
   115  
   116  	cmd := fmt.Sprintf("ping -c 10 -I %s %s", srcip, dstip)
   117  	out, err := c.SSH(a, cmd)
   118  	if err != nil {
   119  		c.Fatalf("ping from %s to %s failed: %s: %v", a.ID(), b.ID(), out, err)
   120  	}
   121  }
   122  
   123  // UDP tests that flannel can send packets using the udp backend.
   124  func udp(c cluster.TestCluster) {
   125  	machs := c.Machines()
   126  
   127  	// Wait for all etcd cluster nodes to be ready.
   128  	if err := etcd.GetClusterHealth(c, machs[0], len(machs)); err != nil {
   129  		c.Fatalf("cluster health: %v", err)
   130  	}
   131  
   132  	ping(c, machs[0], machs[2], "flannel0")
   133  }
   134  
   135  // VXLAN tests that flannel can send packets using the vxlan backend.
   136  func vxlan(c cluster.TestCluster) {
   137  	machs := c.Machines()
   138  
   139  	// Wait for all etcd cluster nodes to be ready.
   140  	if err := etcd.GetClusterHealth(c, machs[0], len(machs)); err != nil {
   141  		c.Fatalf("cluster health: %v", err)
   142  	}
   143  
   144  	ping(c, machs[0], machs[2], "flannel.1")
   145  }