github.com/coreos/mantle@v0.13.0/platform/local/cluster.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 package local 16 17 import ( 18 "fmt" 19 "math/rand" 20 "net" 21 "net/http" 22 "net/url" 23 "strconv" 24 "strings" 25 26 "github.com/vishvananda/netlink" 27 "github.com/vishvananda/netns" 28 29 "github.com/coreos/mantle/lang/destructor" 30 "github.com/coreos/mantle/network" 31 "github.com/coreos/mantle/platform" 32 "github.com/coreos/mantle/system/exec" 33 "github.com/coreos/mantle/system/ns" 34 ) 35 36 type LocalCluster struct { 37 destructor.MultiDestructor 38 *platform.BaseCluster 39 flight *LocalFlight 40 OmahaServer OmahaWrapper 41 } 42 43 func (lc *LocalCluster) NewCommand(name string, arg ...string) exec.Cmd { 44 cmd := ns.Command(lc.flight.nshandle, name, arg...) 45 return cmd 46 } 47 48 func (lc *LocalCluster) hostIP() string { 49 // hackydoo 50 bridge := "br0" 51 for _, seg := range lc.flight.Dnsmasq.Segments { 52 if bridge == seg.BridgeName { 53 return seg.BridgeIf.DHCPv4[0].IP.String() 54 } 55 } 56 panic("Not a valid bridge!") 57 } 58 59 func (lc *LocalCluster) etcdEndpoint() string { 60 return fmt.Sprintf("http://%s:%d", lc.hostIP(), lc.flight.SimpleEtcd.Port) 61 } 62 63 func (lc *LocalCluster) GetDiscoveryURL(size int) (string, error) { 64 baseURL := fmt.Sprintf("%v/v2/keys/discovery/%v", lc.etcdEndpoint(), rand.Int()) 65 66 nsDialer := network.NewNsDialer(lc.flight.nshandle) 67 tr := &http.Transport{ 68 Dial: nsDialer.Dial, 69 } 70 client := &http.Client{Transport: tr} 71 72 body := strings.NewReader(url.Values{"value": {strconv.Itoa(size)}}.Encode()) 73 req, err := http.NewRequest("PUT", baseURL+"/_config/size", body) 74 if err != nil { 75 return "", fmt.Errorf("setting discovery url failed: %v\n", err) 76 } 77 req.Header.Set("Content-Type", "application/x-www-form-urlencoded") 78 79 resp, err := client.Do(req) 80 if err != nil { 81 return "", fmt.Errorf("setting discovery url failed: %v\n", err) 82 } 83 defer resp.Body.Close() 84 85 return baseURL, nil 86 } 87 88 func (lc *LocalCluster) GetOmahaHostPort() (string, error) { 89 _, port, err := net.SplitHostPort(lc.OmahaServer.Addr().String()) 90 if err != nil { 91 return "", err 92 } 93 return net.JoinHostPort(lc.hostIP(), port), nil 94 } 95 96 func (lc *LocalCluster) NewTap(bridge string) (*TunTap, error) { 97 nsExit, err := ns.Enter(lc.flight.nshandle) 98 if err != nil { 99 return nil, err 100 } 101 defer nsExit() 102 103 tap, err := AddLinkTap("") 104 if err != nil { 105 return nil, fmt.Errorf("tap failed: %v", err) 106 } 107 108 err = netlink.LinkSetUp(tap) 109 if err != nil { 110 return nil, fmt.Errorf("tap up failed: %v", err) 111 } 112 113 br, err := netlink.LinkByName(bridge) 114 if err != nil { 115 return nil, fmt.Errorf("bridge failed: %v", err) 116 } 117 118 err = netlink.LinkSetMaster(tap, br.(*netlink.Bridge)) 119 if err != nil { 120 return nil, fmt.Errorf("set master failed: %v", err) 121 } 122 123 return tap, nil 124 } 125 126 func (lc *LocalCluster) GetNsHandle() netns.NsHandle { 127 return lc.flight.nshandle 128 } 129 130 func (lc *LocalCluster) Destroy() { 131 // does not lc.flight.DelCluster() since we are not the top-level object 132 lc.MultiDestructor.Destroy() 133 }