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(®ister.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(®ister.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 }