- removed support for Solaris
- networkdb fixed race on node management
Signed-off-by: Flavio Crisciani <flavio.crisciani@docker.com>
| ... | ... |
@@ -30,7 +30,7 @@ github.com/moby/buildkit aaff9d591ef128560018433fe61beb802e149de8 |
| 30 | 30 |
github.com/tonistiigi/fsutil dea3a0da73aee887fc02142d995be764106ac5e2 |
| 31 | 31 |
|
| 32 | 32 |
#get libnetwork packages |
| 33 |
-github.com/docker/libnetwork 72fd7e5495eba86e28012e39b5ed63ef9ca9a97b |
|
| 33 |
+github.com/docker/libnetwork f7d21337cf1eb628ad54eecac0881fa23ec266df |
|
| 34 | 34 |
github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 |
| 35 | 35 |
github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 |
| 36 | 36 |
github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec |
| 37 | 37 |
deleted file mode 100644 |
| ... | ... |
@@ -1,32 +0,0 @@ |
| 1 |
-package libnetwork |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "strconv" |
|
| 6 |
- |
|
| 7 |
- "github.com/docker/libnetwork/drivers/solaris/bridge" |
|
| 8 |
-) |
|
| 9 |
- |
|
| 10 |
-const libnGWNetwork = "docker_gwbridge" |
|
| 11 |
- |
|
| 12 |
-func getPlatformOption() EndpointOption {
|
|
| 13 |
- return nil |
|
| 14 |
-} |
|
| 15 |
- |
|
| 16 |
-func (c *controller) createGWNetwork() (Network, error) {
|
|
| 17 |
- netOption := map[string]string{
|
|
| 18 |
- bridge.BridgeName: libnGWNetwork, |
|
| 19 |
- bridge.EnableICC: strconv.FormatBool(false), |
|
| 20 |
- bridge.EnableIPMasquerade: strconv.FormatBool(true), |
|
| 21 |
- } |
|
| 22 |
- |
|
| 23 |
- n, err := c.NewNetwork("bridge", libnGWNetwork, "",
|
|
| 24 |
- NetworkOptionDriverOpts(netOption), |
|
| 25 |
- NetworkOptionEnableIPv6(false), |
|
| 26 |
- ) |
|
| 27 |
- |
|
| 28 |
- if err != nil {
|
|
| 29 |
- return nil, fmt.Errorf("error creating external connectivity network: %v", err)
|
|
| 30 |
- } |
|
| 31 |
- return n, err |
|
| 32 |
-} |
| ... | ... |
@@ -81,7 +81,7 @@ func (n *Server) EnableDebug(ip string, port int) {
|
| 81 | 81 |
// go func() {
|
| 82 | 82 |
// http.Serve(n.sk, n.mux) |
| 83 | 83 |
// }() |
| 84 |
- http.ListenAndServe(":8000", n.mux)
|
|
| 84 |
+ http.ListenAndServe(fmt.Sprintf(":%d", port), n.mux)
|
|
| 85 | 85 |
} |
| 86 | 86 |
|
| 87 | 87 |
// DisableDebug stop the dubug and closes the tcp socket |
| 88 | 88 |
deleted file mode 100644 |
| ... | ... |
@@ -1,1263 +0,0 @@ |
| 1 |
-// +build solaris |
|
| 2 |
- |
|
| 3 |
-package bridge |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "bufio" |
|
| 7 |
- "errors" |
|
| 8 |
- "fmt" |
|
| 9 |
- "net" |
|
| 10 |
- "os" |
|
| 11 |
- "os/exec" |
|
| 12 |
- "strconv" |
|
| 13 |
- "strings" |
|
| 14 |
- "sync" |
|
| 15 |
- |
|
| 16 |
- "github.com/docker/libnetwork/datastore" |
|
| 17 |
- "github.com/docker/libnetwork/discoverapi" |
|
| 18 |
- "github.com/docker/libnetwork/driverapi" |
|
| 19 |
- "github.com/docker/libnetwork/iptables" |
|
| 20 |
- "github.com/docker/libnetwork/netlabel" |
|
| 21 |
- "github.com/docker/libnetwork/netutils" |
|
| 22 |
- "github.com/docker/libnetwork/options" |
|
| 23 |
- "github.com/docker/libnetwork/portmapper" |
|
| 24 |
- "github.com/docker/libnetwork/types" |
|
| 25 |
- "github.com/sirupsen/logrus" |
|
| 26 |
-) |
|
| 27 |
- |
|
| 28 |
-const ( |
|
| 29 |
- networkType = "bridge" |
|
| 30 |
- |
|
| 31 |
- // DefaultBridgeName is the default name for the bridge interface managed |
|
| 32 |
- // by the driver when unspecified by the caller. |
|
| 33 |
- DefaultBridgeName = "docker0" |
|
| 34 |
- |
|
| 35 |
- // BridgeName label for bridge driver |
|
| 36 |
- BridgeName = "com.docker.network.bridge.name" |
|
| 37 |
- |
|
| 38 |
- // EnableIPMasquerade label for bridge driver |
|
| 39 |
- EnableIPMasquerade = "com.docker.network.bridge.enable_ip_masquerade" |
|
| 40 |
- |
|
| 41 |
- // EnableICC label |
|
| 42 |
- EnableICC = "com.docker.network.bridge.enable_icc" |
|
| 43 |
- |
|
| 44 |
- // DefaultBindingIP label |
|
| 45 |
- DefaultBindingIP = "com.docker.network.bridge.host_binding_ipv4" |
|
| 46 |
- |
|
| 47 |
- // DefaultBridge label |
|
| 48 |
- DefaultBridge = "com.docker.network.bridge.default_bridge" |
|
| 49 |
- |
|
| 50 |
- // DefaultGatewayV4AuxKey represents the default-gateway configured by the user |
|
| 51 |
- DefaultGatewayV4AuxKey = "DefaultGatewayIPv4" |
|
| 52 |
- |
|
| 53 |
- // DefaultGatewayV6AuxKey represents the ipv6 default-gateway configured by the user |
|
| 54 |
- DefaultGatewayV6AuxKey = "DefaultGatewayIPv6" |
|
| 55 |
-) |
|
| 56 |
- |
|
| 57 |
-// configuration info for the "bridge" driver. |
|
| 58 |
-type configuration struct {
|
|
| 59 |
- EnableIPForwarding bool |
|
| 60 |
- EnableIPTables bool |
|
| 61 |
- EnableUserlandProxy bool |
|
| 62 |
-} |
|
| 63 |
- |
|
| 64 |
-// networkConfiguration for network specific configuration |
|
| 65 |
-type networkConfiguration struct {
|
|
| 66 |
- ID string |
|
| 67 |
- BridgeName string |
|
| 68 |
- BridgeNameInternal string |
|
| 69 |
- EnableIPv6 bool |
|
| 70 |
- EnableIPMasquerade bool |
|
| 71 |
- EnableICC bool |
|
| 72 |
- Mtu int |
|
| 73 |
- DefaultBindingIntf string |
|
| 74 |
- DefaultBindingIP net.IP |
|
| 75 |
- DefaultBridge bool |
|
| 76 |
- // Internal fields set after ipam data parsing |
|
| 77 |
- AddressIPv4 *net.IPNet |
|
| 78 |
- AddressIPv6 *net.IPNet |
|
| 79 |
- DefaultGatewayIPv4 net.IP |
|
| 80 |
- DefaultGatewayIPv6 net.IP |
|
| 81 |
- dbIndex uint64 |
|
| 82 |
- dbExists bool |
|
| 83 |
- Internal bool |
|
| 84 |
-} |
|
| 85 |
- |
|
| 86 |
-// endpointConfiguration represents the user specified configuration for the sandbox endpoint |
|
| 87 |
-type endpointConfiguration struct {
|
|
| 88 |
- MacAddress net.HardwareAddr |
|
| 89 |
- PortBindings []types.PortBinding |
|
| 90 |
- ExposedPorts []types.TransportPort |
|
| 91 |
-} |
|
| 92 |
- |
|
| 93 |
-// containerConfiguration represents the user specified configuration for a container |
|
| 94 |
-type containerConfiguration struct {
|
|
| 95 |
- ParentEndpoints []string |
|
| 96 |
- ChildEndpoints []string |
|
| 97 |
-} |
|
| 98 |
- |
|
| 99 |
-// cnnectivityConfiguration represents the user specified configuration regarding the external connectivity |
|
| 100 |
-type connectivityConfiguration struct {
|
|
| 101 |
- PortBindings []types.PortBinding |
|
| 102 |
- ExposedPorts []types.TransportPort |
|
| 103 |
-} |
|
| 104 |
- |
|
| 105 |
-type bridgeEndpoint struct {
|
|
| 106 |
- id string |
|
| 107 |
- nid string |
|
| 108 |
- srcName string |
|
| 109 |
- addr *net.IPNet |
|
| 110 |
- addrv6 *net.IPNet |
|
| 111 |
- macAddress net.HardwareAddr |
|
| 112 |
- config *endpointConfiguration // User specified parameters |
|
| 113 |
- containerConfig *containerConfiguration |
|
| 114 |
- extConnConfig *connectivityConfiguration |
|
| 115 |
- portMapping []types.PortBinding // Operation port bindings |
|
| 116 |
- dbIndex uint64 |
|
| 117 |
- dbExists bool |
|
| 118 |
-} |
|
| 119 |
- |
|
| 120 |
-type bridgeInterface struct {
|
|
| 121 |
- bridgeIPv4 *net.IPNet |
|
| 122 |
- bridgeIPv6 *net.IPNet |
|
| 123 |
- gatewayIPv4 net.IP |
|
| 124 |
- gatewayIPv6 net.IP |
|
| 125 |
-} |
|
| 126 |
- |
|
| 127 |
-type bridgeNetwork struct {
|
|
| 128 |
- id string |
|
| 129 |
- bridge *bridgeInterface |
|
| 130 |
- config *networkConfiguration |
|
| 131 |
- endpoints map[string]*bridgeEndpoint // key: endpoint id |
|
| 132 |
- portMapper *portmapper.PortMapper |
|
| 133 |
- driver *driver // The network's driver |
|
| 134 |
- sync.Mutex |
|
| 135 |
-} |
|
| 136 |
- |
|
| 137 |
-type driver struct {
|
|
| 138 |
- config *configuration |
|
| 139 |
- network *bridgeNetwork |
|
| 140 |
- natChain *iptables.ChainInfo |
|
| 141 |
- filterChain *iptables.ChainInfo |
|
| 142 |
- isolationChain *iptables.ChainInfo |
|
| 143 |
- networks map[string]*bridgeNetwork |
|
| 144 |
- store datastore.DataStore |
|
| 145 |
- sync.Mutex |
|
| 146 |
- defrouteIP net.IP |
|
| 147 |
-} |
|
| 148 |
- |
|
| 149 |
-// New constructs a new bridge driver |
|
| 150 |
-func newDriver() *driver {
|
|
| 151 |
- return &driver{networks: map[string]*bridgeNetwork{}}
|
|
| 152 |
-} |
|
| 153 |
- |
|
| 154 |
-// Init registers a new instance of bridge driver |
|
| 155 |
-func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
|
| 156 |
- d := newDriver() |
|
| 157 |
- if err := d.configure(config); err != nil {
|
|
| 158 |
- return err |
|
| 159 |
- } |
|
| 160 |
- |
|
| 161 |
- c := driverapi.Capability{
|
|
| 162 |
- DataScope: datastore.LocalScope, |
|
| 163 |
- ConnectivityScope: datastore.LocalScope, |
|
| 164 |
- } |
|
| 165 |
- return dc.RegisterDriver(networkType, d, c) |
|
| 166 |
-} |
|
| 167 |
- |
|
| 168 |
-func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
|
|
| 169 |
- return nil, types.NotImplementedErrorf("not implemented")
|
|
| 170 |
-} |
|
| 171 |
- |
|
| 172 |
-func (d *driver) NetworkFree(id string) error {
|
|
| 173 |
- return types.NotImplementedErrorf("not implemented")
|
|
| 174 |
-} |
|
| 175 |
- |
|
| 176 |
-func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
|
|
| 177 |
-} |
|
| 178 |
- |
|
| 179 |
-func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
|
|
| 180 |
- return "", nil |
|
| 181 |
-} |
|
| 182 |
- |
|
| 183 |
-func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
|
|
| 184 |
- if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" {
|
|
| 185 |
- return types.BadRequestErrorf("ipv4 pool is empty")
|
|
| 186 |
- } |
|
| 187 |
- // Sanity checks |
|
| 188 |
- d.Lock() |
|
| 189 |
- if _, ok := d.networks[id]; ok {
|
|
| 190 |
- d.Unlock() |
|
| 191 |
- return types.ForbiddenErrorf("network %s exists", id)
|
|
| 192 |
- } |
|
| 193 |
- d.Unlock() |
|
| 194 |
- |
|
| 195 |
- // Parse and validate the config. It should not conflict with existing networks' config |
|
| 196 |
- config, err := parseNetworkOptions(d, id, option) |
|
| 197 |
- if err != nil {
|
|
| 198 |
- return err |
|
| 199 |
- } |
|
| 200 |
- |
|
| 201 |
- err = config.processIPAM(id, ipV4Data, ipV6Data) |
|
| 202 |
- if err != nil {
|
|
| 203 |
- return err |
|
| 204 |
- } |
|
| 205 |
- |
|
| 206 |
- if err = d.createNetwork(config); err != nil {
|
|
| 207 |
- return err |
|
| 208 |
- } |
|
| 209 |
- |
|
| 210 |
- return d.storeUpdate(config) |
|
| 211 |
-} |
|
| 212 |
- |
|
| 213 |
-func newInterface(config *networkConfiguration) *bridgeInterface {
|
|
| 214 |
- i := &bridgeInterface{}
|
|
| 215 |
- |
|
| 216 |
- i.bridgeIPv4 = config.AddressIPv4 |
|
| 217 |
- i.gatewayIPv4 = config.AddressIPv4.IP |
|
| 218 |
- if config.BridgeName == "" {
|
|
| 219 |
- config.BridgeName = DefaultBridgeName |
|
| 220 |
- } |
|
| 221 |
- return i |
|
| 222 |
-} |
|
| 223 |
- |
|
| 224 |
-// This function prunes the pf.conf for the firewall |
|
| 225 |
-// that enable the service successfully. |
|
| 226 |
-func fixPFConf() error {
|
|
| 227 |
- conf := "/etc/firewall/pf.conf" |
|
| 228 |
- f, err := os.Open("/etc/firewall/pf.conf")
|
|
| 229 |
- if err != nil {
|
|
| 230 |
- return fmt.Errorf("cannot open %s: %v", conf, err)
|
|
| 231 |
- } |
|
| 232 |
- defer f.Close() |
|
| 233 |
- |
|
| 234 |
- // Look for line beginning with "REMOVE THIS LINE" |
|
| 235 |
- modify := false |
|
| 236 |
- lines := []string{}
|
|
| 237 |
- scanner := bufio.NewScanner(f) |
|
| 238 |
- for scanner.Scan() {
|
|
| 239 |
- l := scanner.Text() |
|
| 240 |
- if strings.Contains(l, "REMOVE THIS LINE") {
|
|
| 241 |
- modify = true |
|
| 242 |
- continue |
|
| 243 |
- } |
|
| 244 |
- lines = append(lines, fmt.Sprintf("%s\n", l))
|
|
| 245 |
- } |
|
| 246 |
- if err = scanner.Err(); err != nil {
|
|
| 247 |
- return fmt.Errorf("cannot open %s: %v", conf, err)
|
|
| 248 |
- } |
|
| 249 |
- |
|
| 250 |
- // No changes needed to fix pf.conf |
|
| 251 |
- if !modify {
|
|
| 252 |
- return nil |
|
| 253 |
- } |
|
| 254 |
- |
|
| 255 |
- // Write back the file removing the line found above |
|
| 256 |
- tmpname := "/etc/firewall/pf.conf.tmp." + strconv.Itoa(os.Getpid()) |
|
| 257 |
- tmp, err := os.OpenFile(tmpname, |
|
| 258 |
- os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_APPEND, 0644) |
|
| 259 |
- if err != nil {
|
|
| 260 |
- return fmt.Errorf("cannot open %s: %v", tmpname, err)
|
|
| 261 |
- } |
|
| 262 |
- defer tmp.Close() |
|
| 263 |
- for _, l := range lines {
|
|
| 264 |
- _, err = tmp.WriteString(l) |
|
| 265 |
- if err != nil {
|
|
| 266 |
- return fmt.Errorf("cannot write to %s: %v",
|
|
| 267 |
- tmpname, err) |
|
| 268 |
- } |
|
| 269 |
- } |
|
| 270 |
- if err = tmp.Sync(); err != nil {
|
|
| 271 |
- return fmt.Errorf("cannot sync %s: %v", tmpname, err)
|
|
| 272 |
- } |
|
| 273 |
- if err = os.Rename(tmpname, conf); err != nil {
|
|
| 274 |
- return fmt.Errorf("cannot rename %s to %s: %v",
|
|
| 275 |
- tmpname, conf, err) |
|
| 276 |
- } |
|
| 277 |
- return nil |
|
| 278 |
-} |
|
| 279 |
- |
|
| 280 |
-func (d *driver) initFirewall() error {
|
|
| 281 |
- out, err := exec.Command("/usr/bin/svcs", "-Ho", "state",
|
|
| 282 |
- "firewall").Output() |
|
| 283 |
- if err != nil {
|
|
| 284 |
- return fmt.Errorf("cannot check firewall state: %v", err)
|
|
| 285 |
- } |
|
| 286 |
- state := strings.TrimSpace(string(out)) |
|
| 287 |
- if state != "online" {
|
|
| 288 |
- if state != "disabled" {
|
|
| 289 |
- return fmt.Errorf("firewall service is in %s state. "+
|
|
| 290 |
- "please enable service manually.", state) |
|
| 291 |
- } |
|
| 292 |
- if err = fixPFConf(); err != nil {
|
|
| 293 |
- return fmt.Errorf("cannot verify pf.conf: %v", err)
|
|
| 294 |
- } |
|
| 295 |
- err = exec.Command("/usr/sbin/svcadm", "enable", "-ts",
|
|
| 296 |
- "firewall").Run() |
|
| 297 |
- if err != nil {
|
|
| 298 |
- return fmt.Errorf("cannot enable firewall service: %v", err)
|
|
| 299 |
- } |
|
| 300 |
- } |
|
| 301 |
- out, err = exec.Command("/usr/sbin/pfctl", "-sr").Output()
|
|
| 302 |
- if err != nil {
|
|
| 303 |
- return fmt.Errorf("failed to list firewall rules: %v", err)
|
|
| 304 |
- } |
|
| 305 |
- if strings.Contains(string(out), "anchor \"_auto/docker/*\" all") {
|
|
| 306 |
- return nil |
|
| 307 |
- } |
|
| 308 |
- pfctlCmd := "(/usr/sbin/pfctl -sr; " + |
|
| 309 |
- "/usr/bin/echo \"anchor \\\"_auto/docker/*\\\"\") |" + |
|
| 310 |
- "/usr/sbin/pfctl -f -" |
|
| 311 |
- err = exec.Command("/usr/bin/bash", "-c", pfctlCmd).Run()
|
|
| 312 |
- if err != nil {
|
|
| 313 |
- return fmt.Errorf("failed to add docker firewall rules: %v", err)
|
|
| 314 |
- } |
|
| 315 |
- return nil |
|
| 316 |
-} |
|
| 317 |
- |
|
| 318 |
-func (d *driver) initRouting() error {
|
|
| 319 |
- err := exec.Command("/usr/sbin/ipadm", "set-prop", "-t",
|
|
| 320 |
- "-p", "forwarding=on", "ipv4").Run() |
|
| 321 |
- if err != nil {
|
|
| 322 |
- return fmt.Errorf("cannot switch-on IP forwarding: %v", err)
|
|
| 323 |
- } |
|
| 324 |
- routeCmd := "/usr/sbin/ipadm show-addr -p -o addr " + |
|
| 325 |
- "`/usr/sbin/route get default | /usr/bin/grep interface | " + |
|
| 326 |
- "/usr/bin/awk '{print $2}'`"
|
|
| 327 |
- out, err := exec.Command("/usr/bin/bash", "-c", routeCmd).Output()
|
|
| 328 |
- if err != nil {
|
|
| 329 |
- return fmt.Errorf("cannot get default route: %v", err)
|
|
| 330 |
- } |
|
| 331 |
- defroute := strings.SplitN(string(out), "/", 2) |
|
| 332 |
- d.defrouteIP = net.ParseIP(defroute[0]) |
|
| 333 |
- if d.defrouteIP == nil {
|
|
| 334 |
- return &ErrNoIPAddr{}
|
|
| 335 |
- } |
|
| 336 |
- return nil |
|
| 337 |
-} |
|
| 338 |
- |
|
| 339 |
-func (d *driver) configure(option map[string]interface{}) error {
|
|
| 340 |
- var err error |
|
| 341 |
- |
|
| 342 |
- if err = d.initFirewall(); err != nil {
|
|
| 343 |
- return fmt.Errorf("failed to configure firewall: %v", err)
|
|
| 344 |
- } |
|
| 345 |
- if err = d.initRouting(); err != nil {
|
|
| 346 |
- return fmt.Errorf("failed to configure routing: %v", err)
|
|
| 347 |
- } |
|
| 348 |
- if err = d.initStore(option); err != nil {
|
|
| 349 |
- return fmt.Errorf("failed to initialize datastore: %v", err)
|
|
| 350 |
- } |
|
| 351 |
- |
|
| 352 |
- return nil |
|
| 353 |
-} |
|
| 354 |
- |
|
| 355 |
-func (d *driver) getNetwork(id string) (*bridgeNetwork, error) {
|
|
| 356 |
- d.Lock() |
|
| 357 |
- defer d.Unlock() |
|
| 358 |
- |
|
| 359 |
- if id == "" {
|
|
| 360 |
- return nil, types.BadRequestErrorf("invalid network id: %s", id)
|
|
| 361 |
- } |
|
| 362 |
- |
|
| 363 |
- if nw, ok := d.networks[id]; ok {
|
|
| 364 |
- return nw, nil |
|
| 365 |
- } |
|
| 366 |
- |
|
| 367 |
- return nil, types.NotFoundErrorf("network not found: %s", id)
|
|
| 368 |
-} |
|
| 369 |
- |
|
| 370 |
-// Return a slice of networks over which caller can iterate safely |
|
| 371 |
-func (d *driver) getNetworks() []*bridgeNetwork {
|
|
| 372 |
- d.Lock() |
|
| 373 |
- defer d.Unlock() |
|
| 374 |
- |
|
| 375 |
- ls := make([]*bridgeNetwork, 0, len(d.networks)) |
|
| 376 |
- for _, nw := range d.networks {
|
|
| 377 |
- ls = append(ls, nw) |
|
| 378 |
- } |
|
| 379 |
- return ls |
|
| 380 |
-} |
|
| 381 |
- |
|
| 382 |
-func bridgeSetup(config *networkConfiguration) error {
|
|
| 383 |
- var err error |
|
| 384 |
- var bindingIntf string |
|
| 385 |
- |
|
| 386 |
- bridgeName := config.BridgeName |
|
| 387 |
- gwName := fmt.Sprintf("%s_gw0", bridgeName)
|
|
| 388 |
- gwIP := config.AddressIPv4.String() |
|
| 389 |
- |
|
| 390 |
- if config.DefaultBindingIP == nil {
|
|
| 391 |
- // Default to net0 if bindingIP is not provided. |
|
| 392 |
- bindingIntf = "net0" |
|
| 393 |
- } else {
|
|
| 394 |
- ipadmCmd := "/usr/sbin/ipadm show-addr -p -o addrobj,addr |" + |
|
| 395 |
- "/usr/bin/grep " + config.DefaultBindingIP.String() |
|
| 396 |
- out, err := exec.Command("/usr/bin/bash", "-c", ipadmCmd).Output()
|
|
| 397 |
- if err != nil {
|
|
| 398 |
- logrus.Warn("cannot find binding interface")
|
|
| 399 |
- return err |
|
| 400 |
- } |
|
| 401 |
- bindingIntf = strings.SplitN(string(out), "/", 2)[0] |
|
| 402 |
- if bindingIntf == "" {
|
|
| 403 |
- logrus.Warnf("cannot parse binding interface %s", string(out))
|
|
| 404 |
- return &ErrNoIPAddr{}
|
|
| 405 |
- } |
|
| 406 |
- } |
|
| 407 |
- config.DefaultBindingIntf = bindingIntf |
|
| 408 |
- |
|
| 409 |
- err = exec.Command("/usr/sbin/dladm", "create-etherstub",
|
|
| 410 |
- "-t", config.BridgeNameInternal).Run() |
|
| 411 |
- if err != nil {
|
|
| 412 |
- logrus.Warnf("cannot create etherstub %s: %+v", config.BridgeNameInternal, err)
|
|
| 413 |
- return err |
|
| 414 |
- } |
|
| 415 |
- err = exec.Command("/usr/sbin/dladm", "create-vnic",
|
|
| 416 |
- "-t", "-l", config.BridgeNameInternal, gwName).Run() |
|
| 417 |
- if err != nil {
|
|
| 418 |
- logrus.Warnf("cannot create vnic %s", gwName)
|
|
| 419 |
- return err |
|
| 420 |
- } |
|
| 421 |
- err = exec.Command("/usr/sbin/ifconfig", gwName,
|
|
| 422 |
- "plumb", gwIP, "up").Run() |
|
| 423 |
- if err != nil {
|
|
| 424 |
- logrus.Warnf("cannot create gateway interface %s on %s",
|
|
| 425 |
- gwIP, gwName) |
|
| 426 |
- return err |
|
| 427 |
- } |
|
| 428 |
- |
|
| 429 |
- tableName := "bridge_nw_subnets" |
|
| 430 |
- pfAnchor := fmt.Sprintf("_auto/docker/%s", tableName)
|
|
| 431 |
- err = exec.Command("/usr/sbin/pfctl", "-a", pfAnchor, "-t", tableName, "-T", "add", gwIP).Run()
|
|
| 432 |
- if err != nil {
|
|
| 433 |
- logrus.Warnf("cannot add bridge network '%s' to PF table", bridgeName)
|
|
| 434 |
- } |
|
| 435 |
- |
|
| 436 |
- pfCmd := fmt.Sprintf( |
|
| 437 |
- "/usr/bin/echo \"pass out on %s from %s:network to any nat-to (%s)\n"+ |
|
| 438 |
- "block in quick from { <%s>, ! %s } to %s\" |"+
|
|
| 439 |
- "/usr/sbin/pfctl -a _auto/docker/%s -f -", |
|
| 440 |
- bindingIntf, gwName, bindingIntf, |
|
| 441 |
- tableName, gwIP, gwIP, |
|
| 442 |
- bridgeName) |
|
| 443 |
- err = exec.Command("/usr/bin/bash", "-c", pfCmd).Run()
|
|
| 444 |
- if err != nil {
|
|
| 445 |
- logrus.Warnf("cannot add pf rule using: %s", pfCmd)
|
|
| 446 |
- return err |
|
| 447 |
- } |
|
| 448 |
- |
|
| 449 |
- return nil |
|
| 450 |
-} |
|
| 451 |
- |
|
| 452 |
-func bridgeCleanup(config *networkConfiguration, logErr bool) {
|
|
| 453 |
- var err error |
|
| 454 |
- |
|
| 455 |
- bridgeName := config.BridgeName |
|
| 456 |
- tableName := "bridge_nw_subnets" |
|
| 457 |
- gwName := fmt.Sprintf("%s_gw0", bridgeName)
|
|
| 458 |
- gwIP := config.AddressIPv4.String() |
|
| 459 |
- pfAnchor := fmt.Sprintf("_auto/docker/%s", bridgeName)
|
|
| 460 |
- tableAnchor := fmt.Sprintf("_auto/docker/%s", tableName)
|
|
| 461 |
- |
|
| 462 |
- err = exec.Command("/usr/sbin/pfctl", "-a", pfAnchor, "-F", "all").Run()
|
|
| 463 |
- if err != nil && logErr {
|
|
| 464 |
- logrus.Warn("cannot flush firewall rules")
|
|
| 465 |
- } |
|
| 466 |
- err = exec.Command("/usr/sbin/ifconfig", gwName, "unplumb").Run()
|
|
| 467 |
- if err != nil && logErr {
|
|
| 468 |
- logrus.Warn("cannot remove gateway interface")
|
|
| 469 |
- } |
|
| 470 |
- err = exec.Command("/usr/sbin/dladm", "delete-vnic",
|
|
| 471 |
- "-t", gwName).Run() |
|
| 472 |
- if err != nil && logErr {
|
|
| 473 |
- logrus.Warn("cannot delete vnic")
|
|
| 474 |
- } |
|
| 475 |
- err = exec.Command("/usr/sbin/dladm", "delete-etherstub",
|
|
| 476 |
- "-t", config.BridgeNameInternal).Run() |
|
| 477 |
- if err != nil && logErr {
|
|
| 478 |
- logrus.Warn("cannot delete etherstub")
|
|
| 479 |
- } |
|
| 480 |
- err = exec.Command("/usr/sbin/pfctl", "-a", tableAnchor, "-t", tableName, "-T", "delete", gwIP).Run()
|
|
| 481 |
- if err != nil && logErr {
|
|
| 482 |
- logrus.Warnf("cannot remove bridge network '%s' from PF table", bridgeName)
|
|
| 483 |
- } |
|
| 484 |
-} |
|
| 485 |
- |
|
| 486 |
-func (d *driver) createNetwork(config *networkConfiguration) error {
|
|
| 487 |
- var err error |
|
| 488 |
- |
|
| 489 |
- logrus.Infof("Creating bridge network: %s %s %s", config.ID,
|
|
| 490 |
- config.BridgeName, config.AddressIPv4) |
|
| 491 |
- |
|
| 492 |
- networkList := d.getNetworks() |
|
| 493 |
- for i, nw := range networkList {
|
|
| 494 |
- nw.Lock() |
|
| 495 |
- nwConfig := nw.config |
|
| 496 |
- nw.Unlock() |
|
| 497 |
- if err := nwConfig.Conflicts(config); err != nil {
|
|
| 498 |
- if config.DefaultBridge {
|
|
| 499 |
- // We encountered and identified a stale default network |
|
| 500 |
- // We must delete it as libnetwork is the source of thruth |
|
| 501 |
- // The default network being created must be the only one |
|
| 502 |
- // This can happen only from docker 1.12 on ward |
|
| 503 |
- logrus.Infof("Removing stale default bridge network %s (%s)", nwConfig.ID, nwConfig.BridgeName)
|
|
| 504 |
- if err := d.DeleteNetwork(nwConfig.ID); err != nil {
|
|
| 505 |
- logrus.Warnf("Failed to remove stale default network: %s (%s): %v. Will remove from store.", nwConfig.ID, nwConfig.BridgeName, err)
|
|
| 506 |
- d.storeDelete(nwConfig) |
|
| 507 |
- } |
|
| 508 |
- networkList = append(networkList[:i], networkList[i+1:]...) |
|
| 509 |
- } else {
|
|
| 510 |
- return types.ForbiddenErrorf( |
|
| 511 |
- "cannot create network %s (%s): "+ |
|
| 512 |
- "conflicts with network %s (%s): %s", |
|
| 513 |
- nwConfig.BridgeName, config.ID, nw.id, |
|
| 514 |
- nw.config.BridgeName, err.Error()) |
|
| 515 |
- } |
|
| 516 |
- } |
|
| 517 |
- } |
|
| 518 |
- if config.DefaultBindingIP == nil || |
|
| 519 |
- config.DefaultBindingIP.IsUnspecified() {
|
|
| 520 |
- config.DefaultBindingIP = d.defrouteIP |
|
| 521 |
- } |
|
| 522 |
- |
|
| 523 |
- // Create and set network handler in driver |
|
| 524 |
- network := &bridgeNetwork{
|
|
| 525 |
- id: config.ID, |
|
| 526 |
- endpoints: make(map[string]*bridgeEndpoint), |
|
| 527 |
- config: config, |
|
| 528 |
- portMapper: portmapper.New(""),
|
|
| 529 |
- driver: d, |
|
| 530 |
- } |
|
| 531 |
- |
|
| 532 |
- d.Lock() |
|
| 533 |
- d.networks[config.ID] = network |
|
| 534 |
- d.Unlock() |
|
| 535 |
- |
|
| 536 |
- // On failure make sure to reset driver network handler to nil |
|
| 537 |
- defer func() {
|
|
| 538 |
- if err != nil {
|
|
| 539 |
- d.Lock() |
|
| 540 |
- delete(d.networks, config.ID) |
|
| 541 |
- d.Unlock() |
|
| 542 |
- } |
|
| 543 |
- }() |
|
| 544 |
- |
|
| 545 |
- // Create or retrieve the bridge L3 interface |
|
| 546 |
- bridgeIface := newInterface(config) |
|
| 547 |
- network.bridge = bridgeIface |
|
| 548 |
- |
|
| 549 |
- // Verify the network configuration does not conflict with previously installed |
|
| 550 |
- // networks. This step is needed now because driver might have now set the bridge |
|
| 551 |
- // name on this config struct. And because we need to check for possible address |
|
| 552 |
- // conflicts, so we need to check against operational networks. |
|
| 553 |
- if err = config.conflictsWithNetworks(config.ID, networkList); err != nil {
|
|
| 554 |
- return err |
|
| 555 |
- } |
|
| 556 |
- |
|
| 557 |
- // We only attempt to create the bridge when the requested device name is |
|
| 558 |
- // the default one. |
|
| 559 |
- if config.BridgeName != DefaultBridgeName && config.DefaultBridge {
|
|
| 560 |
- return NonDefaultBridgeExistError(config.BridgeName) |
|
| 561 |
- } |
|
| 562 |
- |
|
| 563 |
- bridgeCleanup(config, false) |
|
| 564 |
- err = bridgeSetup(config) |
|
| 565 |
- if err != nil {
|
|
| 566 |
- return err |
|
| 567 |
- } |
|
| 568 |
- return nil |
|
| 569 |
-} |
|
| 570 |
- |
|
| 571 |
-func (d *driver) DeleteNetwork(nid string) error {
|
|
| 572 |
- var err error |
|
| 573 |
- // Get network handler and remove it from driver |
|
| 574 |
- d.Lock() |
|
| 575 |
- n, ok := d.networks[nid] |
|
| 576 |
- d.Unlock() |
|
| 577 |
- |
|
| 578 |
- if !ok {
|
|
| 579 |
- return types.InternalMaskableErrorf("network %s does not exist", nid)
|
|
| 580 |
- } |
|
| 581 |
- d.Lock() |
|
| 582 |
- delete(d.networks, nid) |
|
| 583 |
- d.Unlock() |
|
| 584 |
- |
|
| 585 |
- // On failure set network handler back in driver, but |
|
| 586 |
- // only if is not already taken over by some other thread |
|
| 587 |
- defer func() {
|
|
| 588 |
- if err != nil {
|
|
| 589 |
- d.Lock() |
|
| 590 |
- if _, ok := d.networks[nid]; !ok {
|
|
| 591 |
- d.networks[nid] = n |
|
| 592 |
- } |
|
| 593 |
- d.Unlock() |
|
| 594 |
- } |
|
| 595 |
- }() |
|
| 596 |
- |
|
| 597 |
- // Sanity check |
|
| 598 |
- if n == nil {
|
|
| 599 |
- err = driverapi.ErrNoNetwork(nid) |
|
| 600 |
- return err |
|
| 601 |
- } |
|
| 602 |
- |
|
| 603 |
- // Cannot remove network if endpoints are still present |
|
| 604 |
- if len(n.endpoints) != 0 {
|
|
| 605 |
- err = ActiveEndpointsError(n.id) |
|
| 606 |
- return err |
|
| 607 |
- } |
|
| 608 |
- bridgeCleanup(n.config, true) |
|
| 609 |
- logrus.Infof("Deleting bridge network: %s", nid[:12])
|
|
| 610 |
- return d.storeDelete(n.config) |
|
| 611 |
-} |
|
| 612 |
- |
|
| 613 |
-func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
|
|
| 614 |
- if ifInfo == nil {
|
|
| 615 |
- return errors.New("invalid interface passed")
|
|
| 616 |
- } |
|
| 617 |
- |
|
| 618 |
- // Get the network handler and make sure it exists |
|
| 619 |
- d.Lock() |
|
| 620 |
- n, ok := d.networks[nid] |
|
| 621 |
- d.Unlock() |
|
| 622 |
- |
|
| 623 |
- if !ok {
|
|
| 624 |
- return types.NotFoundErrorf("network %s does not exist", nid)
|
|
| 625 |
- } |
|
| 626 |
- if n == nil {
|
|
| 627 |
- return driverapi.ErrNoNetwork(nid) |
|
| 628 |
- } |
|
| 629 |
- |
|
| 630 |
- // Sanity check |
|
| 631 |
- n.Lock() |
|
| 632 |
- if n.id != nid {
|
|
| 633 |
- n.Unlock() |
|
| 634 |
- return InvalidNetworkIDError(nid) |
|
| 635 |
- } |
|
| 636 |
- n.Unlock() |
|
| 637 |
- |
|
| 638 |
- // Check if endpoint id is good and retrieve correspondent endpoint |
|
| 639 |
- ep, err := n.getEndpoint(eid) |
|
| 640 |
- if err != nil {
|
|
| 641 |
- return err |
|
| 642 |
- } |
|
| 643 |
- |
|
| 644 |
- // Endpoint with that id exists either on desired or other sandbox |
|
| 645 |
- if ep != nil {
|
|
| 646 |
- return driverapi.ErrEndpointExists(eid) |
|
| 647 |
- } |
|
| 648 |
- |
|
| 649 |
- // Try to convert the options to endpoint configuration |
|
| 650 |
- epConfig, err := parseEndpointOptions(epOptions) |
|
| 651 |
- if err != nil {
|
|
| 652 |
- return err |
|
| 653 |
- } |
|
| 654 |
- |
|
| 655 |
- // Create and add the endpoint |
|
| 656 |
- n.Lock() |
|
| 657 |
- endpoint := &bridgeEndpoint{id: eid, config: epConfig}
|
|
| 658 |
- n.endpoints[eid] = endpoint |
|
| 659 |
- n.Unlock() |
|
| 660 |
- |
|
| 661 |
- // On failure make sure to remove the endpoint |
|
| 662 |
- defer func() {
|
|
| 663 |
- if err != nil {
|
|
| 664 |
- n.Lock() |
|
| 665 |
- delete(n.endpoints, eid) |
|
| 666 |
- n.Unlock() |
|
| 667 |
- } |
|
| 668 |
- }() |
|
| 669 |
- |
|
| 670 |
- // Create the sandbox side pipe interface |
|
| 671 |
- if ifInfo.MacAddress() == nil {
|
|
| 672 |
- // No MAC address assigned to interface. Generate a random MAC to assign |
|
| 673 |
- endpoint.macAddress = netutils.GenerateRandomMAC() |
|
| 674 |
- if err := ifInfo.SetMacAddress(endpoint.macAddress); err != nil {
|
|
| 675 |
- logrus.Warnf("Unable to set mac address: %s to endpoint: %s",
|
|
| 676 |
- endpoint.macAddress.String(), endpoint.id) |
|
| 677 |
- return err |
|
| 678 |
- } |
|
| 679 |
- } else {
|
|
| 680 |
- endpoint.macAddress = ifInfo.MacAddress() |
|
| 681 |
- } |
|
| 682 |
- endpoint.addr = ifInfo.Address() |
|
| 683 |
- endpoint.addrv6 = ifInfo.AddressIPv6() |
|
| 684 |
- c := n.config |
|
| 685 |
- |
|
| 686 |
- // Program any required port mapping and store them in the endpoint |
|
| 687 |
- endpoint.portMapping, err = n.allocatePorts(endpoint, c.DefaultBindingIntf, c.DefaultBindingIP, true) |
|
| 688 |
- if err != nil {
|
|
| 689 |
- return err |
|
| 690 |
- } |
|
| 691 |
- |
|
| 692 |
- return nil |
|
| 693 |
-} |
|
| 694 |
- |
|
| 695 |
-func (d *driver) DeleteEndpoint(nid, eid string) error {
|
|
| 696 |
- var err error |
|
| 697 |
- |
|
| 698 |
- // Get the network handler and make sure it exists |
|
| 699 |
- d.Lock() |
|
| 700 |
- n, ok := d.networks[nid] |
|
| 701 |
- d.Unlock() |
|
| 702 |
- |
|
| 703 |
- if !ok {
|
|
| 704 |
- return types.InternalMaskableErrorf("network %s does not exist", nid)
|
|
| 705 |
- } |
|
| 706 |
- if n == nil {
|
|
| 707 |
- return driverapi.ErrNoNetwork(nid) |
|
| 708 |
- } |
|
| 709 |
- |
|
| 710 |
- // Sanity Check |
|
| 711 |
- n.Lock() |
|
| 712 |
- if n.id != nid {
|
|
| 713 |
- n.Unlock() |
|
| 714 |
- return InvalidNetworkIDError(nid) |
|
| 715 |
- } |
|
| 716 |
- n.Unlock() |
|
| 717 |
- |
|
| 718 |
- // Check endpoint id and if an endpoint is actually there |
|
| 719 |
- ep, err := n.getEndpoint(eid) |
|
| 720 |
- if err != nil {
|
|
| 721 |
- return err |
|
| 722 |
- } |
|
| 723 |
- if ep == nil {
|
|
| 724 |
- return EndpointNotFoundError(eid) |
|
| 725 |
- } |
|
| 726 |
- |
|
| 727 |
- // Remove it |
|
| 728 |
- n.Lock() |
|
| 729 |
- delete(n.endpoints, eid) |
|
| 730 |
- n.Unlock() |
|
| 731 |
- |
|
| 732 |
- // On failure make sure to set back ep in n.endpoints, but only |
|
| 733 |
- // if it hasn't been taken over already by some other thread. |
|
| 734 |
- defer func() {
|
|
| 735 |
- if err != nil {
|
|
| 736 |
- n.Lock() |
|
| 737 |
- if _, ok := n.endpoints[eid]; !ok {
|
|
| 738 |
- n.endpoints[eid] = ep |
|
| 739 |
- } |
|
| 740 |
- n.Unlock() |
|
| 741 |
- } |
|
| 742 |
- }() |
|
| 743 |
- |
|
| 744 |
- err = n.releasePorts(ep) |
|
| 745 |
- if err != nil {
|
|
| 746 |
- logrus.Warn(err) |
|
| 747 |
- } |
|
| 748 |
- |
|
| 749 |
- return nil |
|
| 750 |
-} |
|
| 751 |
- |
|
| 752 |
-func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
|
|
| 753 |
- // Get the network handler and make sure it exists |
|
| 754 |
- d.Lock() |
|
| 755 |
- n, ok := d.networks[nid] |
|
| 756 |
- d.Unlock() |
|
| 757 |
- if !ok {
|
|
| 758 |
- return nil, types.NotFoundErrorf("network %s does not exist", nid)
|
|
| 759 |
- } |
|
| 760 |
- if n == nil {
|
|
| 761 |
- return nil, driverapi.ErrNoNetwork(nid) |
|
| 762 |
- } |
|
| 763 |
- |
|
| 764 |
- // Sanity check |
|
| 765 |
- n.Lock() |
|
| 766 |
- if n.id != nid {
|
|
| 767 |
- n.Unlock() |
|
| 768 |
- return nil, InvalidNetworkIDError(nid) |
|
| 769 |
- } |
|
| 770 |
- n.Unlock() |
|
| 771 |
- |
|
| 772 |
- // Check if endpoint id is good and retrieve correspondent endpoint |
|
| 773 |
- ep, err := n.getEndpoint(eid) |
|
| 774 |
- if err != nil {
|
|
| 775 |
- return nil, err |
|
| 776 |
- } |
|
| 777 |
- if ep == nil {
|
|
| 778 |
- return nil, driverapi.ErrNoEndpoint(eid) |
|
| 779 |
- } |
|
| 780 |
- |
|
| 781 |
- m := make(map[string]interface{})
|
|
| 782 |
- |
|
| 783 |
- if ep.extConnConfig != nil && ep.extConnConfig.ExposedPorts != nil {
|
|
| 784 |
- // Return a copy of the config data |
|
| 785 |
- epc := make([]types.TransportPort, 0, len(ep.extConnConfig.ExposedPorts)) |
|
| 786 |
- for _, tp := range ep.extConnConfig.ExposedPorts {
|
|
| 787 |
- epc = append(epc, tp.GetCopy()) |
|
| 788 |
- } |
|
| 789 |
- m[netlabel.ExposedPorts] = epc |
|
| 790 |
- } |
|
| 791 |
- |
|
| 792 |
- if ep.portMapping != nil {
|
|
| 793 |
- // Return a copy of the operational data |
|
| 794 |
- pmc := make([]types.PortBinding, 0, len(ep.portMapping)) |
|
| 795 |
- for _, pm := range ep.portMapping {
|
|
| 796 |
- pmc = append(pmc, pm.GetCopy()) |
|
| 797 |
- } |
|
| 798 |
- m[netlabel.PortMap] = pmc |
|
| 799 |
- } |
|
| 800 |
- |
|
| 801 |
- if len(ep.macAddress) != 0 {
|
|
| 802 |
- m[netlabel.MacAddress] = ep.macAddress |
|
| 803 |
- } |
|
| 804 |
- return m, nil |
|
| 805 |
-} |
|
| 806 |
- |
|
| 807 |
-// Join method is invoked when a Sandbox is attached to an endpoint. |
|
| 808 |
-func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
|
| 809 |
- network, err := d.getNetwork(nid) |
|
| 810 |
- if err != nil {
|
|
| 811 |
- return err |
|
| 812 |
- } |
|
| 813 |
- |
|
| 814 |
- endpoint, err := network.getEndpoint(eid) |
|
| 815 |
- if err != nil {
|
|
| 816 |
- return err |
|
| 817 |
- } |
|
| 818 |
- |
|
| 819 |
- if endpoint == nil {
|
|
| 820 |
- return EndpointNotFoundError(eid) |
|
| 821 |
- } |
|
| 822 |
- |
|
| 823 |
- endpoint.containerConfig, err = parseContainerOptions(options) |
|
| 824 |
- if err != nil {
|
|
| 825 |
- return err |
|
| 826 |
- } |
|
| 827 |
- |
|
| 828 |
- err = jinfo.SetGateway(network.bridge.gatewayIPv4) |
|
| 829 |
- if err != nil {
|
|
| 830 |
- return err |
|
| 831 |
- } |
|
| 832 |
- |
|
| 833 |
- err = jinfo.SetGatewayIPv6(network.bridge.gatewayIPv6) |
|
| 834 |
- if err != nil {
|
|
| 835 |
- return err |
|
| 836 |
- } |
|
| 837 |
- |
|
| 838 |
- return nil |
|
| 839 |
-} |
|
| 840 |
- |
|
| 841 |
-func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, enable bool) error {
|
|
| 842 |
- return nil |
|
| 843 |
-} |
|
| 844 |
- |
|
| 845 |
-// Leave method is invoked when a Sandbox detaches from an endpoint. |
|
| 846 |
-func (d *driver) Leave(nid, eid string) error {
|
|
| 847 |
- network, err := d.getNetwork(nid) |
|
| 848 |
- if err != nil {
|
|
| 849 |
- return types.InternalMaskableErrorf("%s", err)
|
|
| 850 |
- } |
|
| 851 |
- |
|
| 852 |
- endpoint, err := network.getEndpoint(eid) |
|
| 853 |
- if err != nil {
|
|
| 854 |
- return err |
|
| 855 |
- } |
|
| 856 |
- |
|
| 857 |
- if endpoint == nil {
|
|
| 858 |
- return EndpointNotFoundError(eid) |
|
| 859 |
- } |
|
| 860 |
- |
|
| 861 |
- return nil |
|
| 862 |
-} |
|
| 863 |
- |
|
| 864 |
-func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
|
| 865 |
- network, err := d.getNetwork(nid) |
|
| 866 |
- if err != nil {
|
|
| 867 |
- return err |
|
| 868 |
- } |
|
| 869 |
- |
|
| 870 |
- endpoint, err := network.getEndpoint(eid) |
|
| 871 |
- if err != nil {
|
|
| 872 |
- return err |
|
| 873 |
- } |
|
| 874 |
- |
|
| 875 |
- if endpoint == nil {
|
|
| 876 |
- return EndpointNotFoundError(eid) |
|
| 877 |
- } |
|
| 878 |
- |
|
| 879 |
- endpoint.extConnConfig, err = parseConnectivityOptions(options) |
|
| 880 |
- if err != nil {
|
|
| 881 |
- return err |
|
| 882 |
- } |
|
| 883 |
- |
|
| 884 |
- // Program any required port mapping and store them in the endpoint |
|
| 885 |
- endpoint.portMapping, err = network.allocatePorts(endpoint, network.config.DefaultBindingIntf, network.config.DefaultBindingIP, true) |
|
| 886 |
- if err != nil {
|
|
| 887 |
- return err |
|
| 888 |
- } |
|
| 889 |
- |
|
| 890 |
- if !network.config.EnableICC {
|
|
| 891 |
- return d.link(network, endpoint, true) |
|
| 892 |
- } |
|
| 893 |
- |
|
| 894 |
- return nil |
|
| 895 |
-} |
|
| 896 |
- |
|
| 897 |
-func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
|
| 898 |
- network, err := d.getNetwork(nid) |
|
| 899 |
- if err != nil {
|
|
| 900 |
- return err |
|
| 901 |
- } |
|
| 902 |
- |
|
| 903 |
- endpoint, err := network.getEndpoint(eid) |
|
| 904 |
- if err != nil {
|
|
| 905 |
- return err |
|
| 906 |
- } |
|
| 907 |
- |
|
| 908 |
- if endpoint == nil {
|
|
| 909 |
- return EndpointNotFoundError(eid) |
|
| 910 |
- } |
|
| 911 |
- |
|
| 912 |
- err = network.releasePorts(endpoint) |
|
| 913 |
- if err != nil {
|
|
| 914 |
- logrus.Warn(err) |
|
| 915 |
- } |
|
| 916 |
- |
|
| 917 |
- return nil |
|
| 918 |
-} |
|
| 919 |
- |
|
| 920 |
-func (d *driver) Type() string {
|
|
| 921 |
- return networkType |
|
| 922 |
-} |
|
| 923 |
- |
|
| 924 |
-func (d *driver) IsBuiltIn() bool {
|
|
| 925 |
- return true |
|
| 926 |
-} |
|
| 927 |
- |
|
| 928 |
-// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster |
|
| 929 |
-func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
|
| 930 |
- return nil |
|
| 931 |
-} |
|
| 932 |
- |
|
| 933 |
-// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster |
|
| 934 |
-func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
|
| 935 |
- return nil |
|
| 936 |
-} |
|
| 937 |
- |
|
| 938 |
-// Validate performs a static validation on the network configuration parameters. |
|
| 939 |
-// Whatever can be assessed a priori before attempting any programming. |
|
| 940 |
-func (c *networkConfiguration) Validate() error {
|
|
| 941 |
- if c.Mtu < 0 {
|
|
| 942 |
- return ErrInvalidMtu(c.Mtu) |
|
| 943 |
- } |
|
| 944 |
- |
|
| 945 |
- // If bridge v4 subnet is specified |
|
| 946 |
- if c.AddressIPv4 != nil {
|
|
| 947 |
- // If default gw is specified, it must be part of bridge subnet |
|
| 948 |
- if c.DefaultGatewayIPv4 != nil {
|
|
| 949 |
- if !c.AddressIPv4.Contains(c.DefaultGatewayIPv4) {
|
|
| 950 |
- return &ErrInvalidGateway{}
|
|
| 951 |
- } |
|
| 952 |
- } |
|
| 953 |
- } |
|
| 954 |
- |
|
| 955 |
- // If default v6 gw is specified, AddressIPv6 must be specified and gw must belong to AddressIPv6 subnet |
|
| 956 |
- if c.EnableIPv6 && c.DefaultGatewayIPv6 != nil {
|
|
| 957 |
- if c.AddressIPv6 == nil || !c.AddressIPv6.Contains(c.DefaultGatewayIPv6) {
|
|
| 958 |
- return &ErrInvalidGateway{}
|
|
| 959 |
- } |
|
| 960 |
- } |
|
| 961 |
- return nil |
|
| 962 |
-} |
|
| 963 |
- |
|
| 964 |
-// Checks whether this network's configuration for the network with this id conflicts with any of the passed networks |
|
| 965 |
-func (c *networkConfiguration) conflictsWithNetworks(id string, others []*bridgeNetwork) error {
|
|
| 966 |
- for _, nw := range others {
|
|
| 967 |
- |
|
| 968 |
- nw.Lock() |
|
| 969 |
- nwID := nw.id |
|
| 970 |
- nwConfig := nw.config |
|
| 971 |
- nwBridge := nw.bridge |
|
| 972 |
- nw.Unlock() |
|
| 973 |
- |
|
| 974 |
- if nwID == id {
|
|
| 975 |
- continue |
|
| 976 |
- } |
|
| 977 |
- // Verify the name (which may have been set by newInterface()) does not conflict with |
|
| 978 |
- // existing bridge interfaces. Ironically the system chosen name gets stored in the config... |
|
| 979 |
- // Basically we are checking if the two original configs were both empty. |
|
| 980 |
- if nwConfig.BridgeName == c.BridgeName {
|
|
| 981 |
- return types.ForbiddenErrorf("conflicts with network %s (%s) by bridge name", nwID, nwConfig.BridgeName)
|
|
| 982 |
- } |
|
| 983 |
- // If this network config specifies the AddressIPv4, we need |
|
| 984 |
- // to make sure it does not conflict with any previously allocated |
|
| 985 |
- // bridges. This could not be completely caught by the config conflict |
|
| 986 |
- // check, because networks which config does not specify the AddressIPv4 |
|
| 987 |
- // get their address and subnet selected by the driver (see electBridgeIPv4()) |
|
| 988 |
- if c.AddressIPv4 != nil {
|
|
| 989 |
- if nwBridge.bridgeIPv4.Contains(c.AddressIPv4.IP) || |
|
| 990 |
- c.AddressIPv4.Contains(nwBridge.bridgeIPv4.IP) {
|
|
| 991 |
- return types.ForbiddenErrorf("conflicts with network %s (%s) by ip network", nwID, nwConfig.BridgeName)
|
|
| 992 |
- } |
|
| 993 |
- } |
|
| 994 |
- } |
|
| 995 |
- |
|
| 996 |
- return nil |
|
| 997 |
-} |
|
| 998 |
- |
|
| 999 |
-// Conflicts check if two NetworkConfiguration objects overlap |
|
| 1000 |
-func (c *networkConfiguration) Conflicts(o *networkConfiguration) error {
|
|
| 1001 |
- if o == nil {
|
|
| 1002 |
- return fmt.Errorf("same configuration")
|
|
| 1003 |
- } |
|
| 1004 |
- |
|
| 1005 |
- // Also empty, because only one network with empty name is allowed |
|
| 1006 |
- if c.BridgeName == o.BridgeName {
|
|
| 1007 |
- return fmt.Errorf("networks have same bridge name")
|
|
| 1008 |
- } |
|
| 1009 |
- |
|
| 1010 |
- // They must be in different subnets |
|
| 1011 |
- if (c.AddressIPv4 != nil && o.AddressIPv4 != nil) && |
|
| 1012 |
- (c.AddressIPv4.Contains(o.AddressIPv4.IP) || o.AddressIPv4.Contains(c.AddressIPv4.IP)) {
|
|
| 1013 |
- return fmt.Errorf("networks have overlapping IPv4")
|
|
| 1014 |
- } |
|
| 1015 |
- |
|
| 1016 |
- // They must be in different v6 subnets |
|
| 1017 |
- if (c.AddressIPv6 != nil && o.AddressIPv6 != nil) && |
|
| 1018 |
- (c.AddressIPv6.Contains(o.AddressIPv6.IP) || o.AddressIPv6.Contains(c.AddressIPv6.IP)) {
|
|
| 1019 |
- return fmt.Errorf("networks have overlapping IPv6")
|
|
| 1020 |
- } |
|
| 1021 |
- |
|
| 1022 |
- return nil |
|
| 1023 |
-} |
|
| 1024 |
- |
|
| 1025 |
-func (c *networkConfiguration) fromLabels(labels map[string]string) error {
|
|
| 1026 |
- var err error |
|
| 1027 |
- for label, value := range labels {
|
|
| 1028 |
- switch label {
|
|
| 1029 |
- case BridgeName: |
|
| 1030 |
- c.BridgeName = value |
|
| 1031 |
- case netlabel.DriverMTU: |
|
| 1032 |
- if c.Mtu, err = strconv.Atoi(value); err != nil {
|
|
| 1033 |
- return parseErr(label, value, err.Error()) |
|
| 1034 |
- } |
|
| 1035 |
- case netlabel.EnableIPv6: |
|
| 1036 |
- if c.EnableIPv6, err = strconv.ParseBool(value); err != nil {
|
|
| 1037 |
- return parseErr(label, value, err.Error()) |
|
| 1038 |
- } |
|
| 1039 |
- case EnableIPMasquerade: |
|
| 1040 |
- if c.EnableIPMasquerade, err = strconv.ParseBool(value); err != nil {
|
|
| 1041 |
- return parseErr(label, value, err.Error()) |
|
| 1042 |
- } |
|
| 1043 |
- case EnableICC: |
|
| 1044 |
- if c.EnableICC, err = strconv.ParseBool(value); err != nil {
|
|
| 1045 |
- return parseErr(label, value, err.Error()) |
|
| 1046 |
- } |
|
| 1047 |
- case DefaultBridge: |
|
| 1048 |
- if c.DefaultBridge, err = strconv.ParseBool(value); err != nil {
|
|
| 1049 |
- return parseErr(label, value, err.Error()) |
|
| 1050 |
- } |
|
| 1051 |
- case DefaultBindingIP: |
|
| 1052 |
- if c.DefaultBindingIP = net.ParseIP(value); c.DefaultBindingIP == nil {
|
|
| 1053 |
- return parseErr(label, value, "nil ip") |
|
| 1054 |
- } |
|
| 1055 |
- } |
|
| 1056 |
- } |
|
| 1057 |
- |
|
| 1058 |
- return nil |
|
| 1059 |
-} |
|
| 1060 |
- |
|
| 1061 |
-func parseErr(label, value, errString string) error {
|
|
| 1062 |
- return types.BadRequestErrorf("failed to parse %s value: %v (%s)", label, value, errString)
|
|
| 1063 |
-} |
|
| 1064 |
- |
|
| 1065 |
-func parseNetworkGenericOptions(data interface{}) (*networkConfiguration, error) {
|
|
| 1066 |
- var ( |
|
| 1067 |
- err error |
|
| 1068 |
- config *networkConfiguration |
|
| 1069 |
- ) |
|
| 1070 |
- |
|
| 1071 |
- switch opt := data.(type) {
|
|
| 1072 |
- case *networkConfiguration: |
|
| 1073 |
- config = opt |
|
| 1074 |
- case map[string]string: |
|
| 1075 |
- config = &networkConfiguration{
|
|
| 1076 |
- EnableICC: true, |
|
| 1077 |
- EnableIPMasquerade: true, |
|
| 1078 |
- } |
|
| 1079 |
- err = config.fromLabels(opt) |
|
| 1080 |
- case options.Generic: |
|
| 1081 |
- var opaqueConfig interface{}
|
|
| 1082 |
- if opaqueConfig, err = options.GenerateFromModel(opt, config); err == nil {
|
|
| 1083 |
- config = opaqueConfig.(*networkConfiguration) |
|
| 1084 |
- } |
|
| 1085 |
- default: |
|
| 1086 |
- err = types.BadRequestErrorf("do not recognize network configuration format: %T", opt)
|
|
| 1087 |
- } |
|
| 1088 |
- |
|
| 1089 |
- return config, err |
|
| 1090 |
-} |
|
| 1091 |
- |
|
| 1092 |
-func parseNetworkOptions(d *driver, id string, option options.Generic) (*networkConfiguration, error) {
|
|
| 1093 |
- var ( |
|
| 1094 |
- err error |
|
| 1095 |
- config = &networkConfiguration{}
|
|
| 1096 |
- ) |
|
| 1097 |
- |
|
| 1098 |
- // Parse generic label first, config will be re-assigned |
|
| 1099 |
- if genData, ok := option[netlabel.GenericData]; ok && genData != nil {
|
|
| 1100 |
- if config, err = parseNetworkGenericOptions(genData); err != nil {
|
|
| 1101 |
- return nil, err |
|
| 1102 |
- } |
|
| 1103 |
- } |
|
| 1104 |
- |
|
| 1105 |
- // Process well-known labels next |
|
| 1106 |
- if val, ok := option[netlabel.EnableIPv6]; ok {
|
|
| 1107 |
- config.EnableIPv6 = val.(bool) |
|
| 1108 |
- } |
|
| 1109 |
- |
|
| 1110 |
- if val, ok := option[netlabel.Internal]; ok {
|
|
| 1111 |
- if internal, ok := val.(bool); ok && internal {
|
|
| 1112 |
- config.Internal = true |
|
| 1113 |
- } |
|
| 1114 |
- } |
|
| 1115 |
- |
|
| 1116 |
- // Finally validate the configuration |
|
| 1117 |
- if err = config.Validate(); err != nil {
|
|
| 1118 |
- return nil, err |
|
| 1119 |
- } |
|
| 1120 |
- |
|
| 1121 |
- if config.BridgeName == "" && config.DefaultBridge == false {
|
|
| 1122 |
- config.BridgeName = "br_" + id[:12] + "_0" |
|
| 1123 |
- } |
|
| 1124 |
- |
|
| 1125 |
- lastChar := config.BridgeName[len(config.BridgeName)-1:] |
|
| 1126 |
- if _, err = strconv.Atoi(lastChar); err != nil {
|
|
| 1127 |
- config.BridgeNameInternal = config.BridgeName + "_0" |
|
| 1128 |
- } else {
|
|
| 1129 |
- config.BridgeNameInternal = config.BridgeName |
|
| 1130 |
- } |
|
| 1131 |
- |
|
| 1132 |
- config.ID = id |
|
| 1133 |
- return config, nil |
|
| 1134 |
-} |
|
| 1135 |
- |
|
| 1136 |
-func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error {
|
|
| 1137 |
- if len(ipamV4Data) > 1 || len(ipamV6Data) > 1 {
|
|
| 1138 |
- return types.ForbiddenErrorf("bridge driver doesnt support multiple subnets")
|
|
| 1139 |
- } |
|
| 1140 |
- |
|
| 1141 |
- if len(ipamV4Data) == 0 {
|
|
| 1142 |
- return types.BadRequestErrorf("bridge network %s requires ipv4 configuration", id)
|
|
| 1143 |
- } |
|
| 1144 |
- |
|
| 1145 |
- if ipamV4Data[0].Gateway != nil {
|
|
| 1146 |
- c.AddressIPv4 = types.GetIPNetCopy(ipamV4Data[0].Gateway) |
|
| 1147 |
- } |
|
| 1148 |
- |
|
| 1149 |
- if gw, ok := ipamV4Data[0].AuxAddresses[DefaultGatewayV4AuxKey]; ok {
|
|
| 1150 |
- c.DefaultGatewayIPv4 = gw.IP |
|
| 1151 |
- } |
|
| 1152 |
- |
|
| 1153 |
- if len(ipamV6Data) > 0 {
|
|
| 1154 |
- c.AddressIPv6 = ipamV6Data[0].Pool |
|
| 1155 |
- |
|
| 1156 |
- if ipamV6Data[0].Gateway != nil {
|
|
| 1157 |
- c.AddressIPv6 = types.GetIPNetCopy(ipamV6Data[0].Gateway) |
|
| 1158 |
- } |
|
| 1159 |
- |
|
| 1160 |
- if gw, ok := ipamV6Data[0].AuxAddresses[DefaultGatewayV6AuxKey]; ok {
|
|
| 1161 |
- c.DefaultGatewayIPv6 = gw.IP |
|
| 1162 |
- } |
|
| 1163 |
- } |
|
| 1164 |
- |
|
| 1165 |
- return nil |
|
| 1166 |
-} |
|
| 1167 |
- |
|
| 1168 |
-func (n *bridgeNetwork) getEndpoint(eid string) (*bridgeEndpoint, error) {
|
|
| 1169 |
- n.Lock() |
|
| 1170 |
- defer n.Unlock() |
|
| 1171 |
- |
|
| 1172 |
- if eid == "" {
|
|
| 1173 |
- return nil, InvalidEndpointIDError(eid) |
|
| 1174 |
- } |
|
| 1175 |
- |
|
| 1176 |
- if ep, ok := n.endpoints[eid]; ok {
|
|
| 1177 |
- return ep, nil |
|
| 1178 |
- } |
|
| 1179 |
- |
|
| 1180 |
- return nil, nil |
|
| 1181 |
-} |
|
| 1182 |
- |
|
| 1183 |
-func parseEndpointOptions(epOptions map[string]interface{}) (*endpointConfiguration, error) {
|
|
| 1184 |
- if epOptions == nil {
|
|
| 1185 |
- return nil, nil |
|
| 1186 |
- } |
|
| 1187 |
- |
|
| 1188 |
- ec := &endpointConfiguration{}
|
|
| 1189 |
- |
|
| 1190 |
- if opt, ok := epOptions[netlabel.MacAddress]; ok {
|
|
| 1191 |
- if mac, ok := opt.(net.HardwareAddr); ok {
|
|
| 1192 |
- ec.MacAddress = mac |
|
| 1193 |
- } else {
|
|
| 1194 |
- return nil, &ErrInvalidEndpointConfig{}
|
|
| 1195 |
- } |
|
| 1196 |
- } |
|
| 1197 |
- |
|
| 1198 |
- if opt, ok := epOptions[netlabel.PortMap]; ok {
|
|
| 1199 |
- if bs, ok := opt.([]types.PortBinding); ok {
|
|
| 1200 |
- ec.PortBindings = bs |
|
| 1201 |
- } else {
|
|
| 1202 |
- return nil, &ErrInvalidEndpointConfig{}
|
|
| 1203 |
- } |
|
| 1204 |
- } |
|
| 1205 |
- |
|
| 1206 |
- if opt, ok := epOptions[netlabel.ExposedPorts]; ok {
|
|
| 1207 |
- if ports, ok := opt.([]types.TransportPort); ok {
|
|
| 1208 |
- ec.ExposedPorts = ports |
|
| 1209 |
- } else {
|
|
| 1210 |
- return nil, &ErrInvalidEndpointConfig{}
|
|
| 1211 |
- } |
|
| 1212 |
- } |
|
| 1213 |
- |
|
| 1214 |
- return ec, nil |
|
| 1215 |
-} |
|
| 1216 |
- |
|
| 1217 |
-func parseContainerOptions(cOptions map[string]interface{}) (*containerConfiguration, error) {
|
|
| 1218 |
- if cOptions == nil {
|
|
| 1219 |
- return nil, nil |
|
| 1220 |
- } |
|
| 1221 |
- genericData := cOptions[netlabel.GenericData] |
|
| 1222 |
- if genericData == nil {
|
|
| 1223 |
- return nil, nil |
|
| 1224 |
- } |
|
| 1225 |
- switch opt := genericData.(type) {
|
|
| 1226 |
- case options.Generic: |
|
| 1227 |
- opaqueConfig, err := options.GenerateFromModel(opt, &containerConfiguration{})
|
|
| 1228 |
- if err != nil {
|
|
| 1229 |
- return nil, err |
|
| 1230 |
- } |
|
| 1231 |
- return opaqueConfig.(*containerConfiguration), nil |
|
| 1232 |
- case *containerConfiguration: |
|
| 1233 |
- return opt, nil |
|
| 1234 |
- default: |
|
| 1235 |
- return nil, nil |
|
| 1236 |
- } |
|
| 1237 |
-} |
|
| 1238 |
- |
|
| 1239 |
-func parseConnectivityOptions(cOptions map[string]interface{}) (*connectivityConfiguration, error) {
|
|
| 1240 |
- if cOptions == nil {
|
|
| 1241 |
- return nil, nil |
|
| 1242 |
- } |
|
| 1243 |
- |
|
| 1244 |
- cc := &connectivityConfiguration{}
|
|
| 1245 |
- |
|
| 1246 |
- if opt, ok := cOptions[netlabel.PortMap]; ok {
|
|
| 1247 |
- if pb, ok := opt.([]types.PortBinding); ok {
|
|
| 1248 |
- cc.PortBindings = pb |
|
| 1249 |
- } else {
|
|
| 1250 |
- return nil, types.BadRequestErrorf("Invalid port mapping data in connectivity configuration: %v", opt)
|
|
| 1251 |
- } |
|
| 1252 |
- } |
|
| 1253 |
- |
|
| 1254 |
- if opt, ok := cOptions[netlabel.ExposedPorts]; ok {
|
|
| 1255 |
- if ports, ok := opt.([]types.TransportPort); ok {
|
|
| 1256 |
- cc.ExposedPorts = ports |
|
| 1257 |
- } else {
|
|
| 1258 |
- return nil, types.BadRequestErrorf("Invalid exposed ports data in connectivity configuration: %v", opt)
|
|
| 1259 |
- } |
|
| 1260 |
- } |
|
| 1261 |
- |
|
| 1262 |
- return cc, nil |
|
| 1263 |
-} |
| 1264 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,384 +0,0 @@ |
| 1 |
-// +build solaris |
|
| 2 |
- |
|
| 3 |
-package bridge |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "encoding/json" |
|
| 7 |
- "fmt" |
|
| 8 |
- "net" |
|
| 9 |
- |
|
| 10 |
- "github.com/docker/libnetwork/datastore" |
|
| 11 |
- "github.com/docker/libnetwork/discoverapi" |
|
| 12 |
- "github.com/docker/libnetwork/netlabel" |
|
| 13 |
- "github.com/docker/libnetwork/types" |
|
| 14 |
- "github.com/sirupsen/logrus" |
|
| 15 |
-) |
|
| 16 |
- |
|
| 17 |
-const ( |
|
| 18 |
- // network config prefix was not specific enough. |
|
| 19 |
- // To be backward compatible, need custom endpoint |
|
| 20 |
- // prefix with different root |
|
| 21 |
- bridgePrefix = "bridge" |
|
| 22 |
- bridgeEndpointPrefix = "bridge-endpoint" |
|
| 23 |
-) |
|
| 24 |
- |
|
| 25 |
-func (d *driver) initStore(option map[string]interface{}) error {
|
|
| 26 |
- if data, ok := option[netlabel.LocalKVClient]; ok {
|
|
| 27 |
- var err error |
|
| 28 |
- dsc, ok := data.(discoverapi.DatastoreConfigData) |
|
| 29 |
- if !ok {
|
|
| 30 |
- return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
|
| 31 |
- } |
|
| 32 |
- d.store, err = datastore.NewDataStoreFromConfig(dsc) |
|
| 33 |
- if err != nil {
|
|
| 34 |
- return types.InternalErrorf("bridge driver failed to initialize data store: %v", err)
|
|
| 35 |
- } |
|
| 36 |
- |
|
| 37 |
- err = d.populateNetworks() |
|
| 38 |
- if err != nil {
|
|
| 39 |
- return err |
|
| 40 |
- } |
|
| 41 |
- |
|
| 42 |
- err = d.populateEndpoints() |
|
| 43 |
- if err != nil {
|
|
| 44 |
- return err |
|
| 45 |
- } |
|
| 46 |
- } |
|
| 47 |
- |
|
| 48 |
- return nil |
|
| 49 |
-} |
|
| 50 |
- |
|
| 51 |
-func (d *driver) populateNetworks() error {
|
|
| 52 |
- kvol, err := d.store.List(datastore.Key(bridgePrefix), &networkConfiguration{})
|
|
| 53 |
- if err != nil && err != datastore.ErrKeyNotFound {
|
|
| 54 |
- return fmt.Errorf("failed to get bridge network configurations from store: %v", err)
|
|
| 55 |
- } |
|
| 56 |
- |
|
| 57 |
- // It's normal for network configuration state to be empty. Just return. |
|
| 58 |
- if err == datastore.ErrKeyNotFound {
|
|
| 59 |
- return nil |
|
| 60 |
- } |
|
| 61 |
- |
|
| 62 |
- for _, kvo := range kvol {
|
|
| 63 |
- ncfg := kvo.(*networkConfiguration) |
|
| 64 |
- if err = d.createNetwork(ncfg); err != nil {
|
|
| 65 |
- logrus.Warnf("could not create bridge network for id %s bridge name %s while booting up from persistent state: %v", ncfg.ID, ncfg.BridgeName, err)
|
|
| 66 |
- } |
|
| 67 |
- logrus.Debugf("Network (%s) restored", ncfg.ID[0:7])
|
|
| 68 |
- } |
|
| 69 |
- |
|
| 70 |
- return nil |
|
| 71 |
-} |
|
| 72 |
- |
|
| 73 |
-func (d *driver) populateEndpoints() error {
|
|
| 74 |
- kvol, err := d.store.List(datastore.Key(bridgeEndpointPrefix), &bridgeEndpoint{})
|
|
| 75 |
- if err != nil && err != datastore.ErrKeyNotFound {
|
|
| 76 |
- return fmt.Errorf("failed to get bridge endpoints from store: %v", err)
|
|
| 77 |
- } |
|
| 78 |
- |
|
| 79 |
- if err == datastore.ErrKeyNotFound {
|
|
| 80 |
- return nil |
|
| 81 |
- } |
|
| 82 |
- |
|
| 83 |
- for _, kvo := range kvol {
|
|
| 84 |
- ep := kvo.(*bridgeEndpoint) |
|
| 85 |
- n, ok := d.networks[ep.nid] |
|
| 86 |
- if !ok {
|
|
| 87 |
- logrus.Debugf("Network (%s) not found for restored bridge endpoint (%s)", ep.nid[0:7], ep.id[0:7])
|
|
| 88 |
- logrus.Debugf("Deleting stale bridge endpoint (%s) from store", ep.nid[0:7])
|
|
| 89 |
- if err := d.storeDelete(ep); err != nil {
|
|
| 90 |
- logrus.Debugf("Failed to delete stale bridge endpoint (%s) from store", ep.nid[0:7])
|
|
| 91 |
- } |
|
| 92 |
- continue |
|
| 93 |
- } |
|
| 94 |
- n.endpoints[ep.id] = ep |
|
| 95 |
- n.restorePortAllocations(ep) |
|
| 96 |
- logrus.Debugf("Endpoint (%s) restored to network (%s)", ep.id[0:7], ep.nid[0:7])
|
|
| 97 |
- } |
|
| 98 |
- |
|
| 99 |
- return nil |
|
| 100 |
-} |
|
| 101 |
- |
|
| 102 |
-func (d *driver) storeUpdate(kvObject datastore.KVObject) error {
|
|
| 103 |
- if d.store == nil {
|
|
| 104 |
- logrus.Warnf("bridge store not initialized. kv object %s is not added to the store", datastore.Key(kvObject.Key()...))
|
|
| 105 |
- return nil |
|
| 106 |
- } |
|
| 107 |
- |
|
| 108 |
- if err := d.store.PutObjectAtomic(kvObject); err != nil {
|
|
| 109 |
- return fmt.Errorf("failed to update bridge store for object type %T: %v", kvObject, err)
|
|
| 110 |
- } |
|
| 111 |
- |
|
| 112 |
- return nil |
|
| 113 |
-} |
|
| 114 |
- |
|
| 115 |
-func (d *driver) storeDelete(kvObject datastore.KVObject) error {
|
|
| 116 |
- if d.store == nil {
|
|
| 117 |
- logrus.Debugf("bridge store not initialized. kv object %s is not deleted from store", datastore.Key(kvObject.Key()...))
|
|
| 118 |
- return nil |
|
| 119 |
- } |
|
| 120 |
- |
|
| 121 |
-retry: |
|
| 122 |
- if err := d.store.DeleteObjectAtomic(kvObject); err != nil {
|
|
| 123 |
- if err == datastore.ErrKeyModified {
|
|
| 124 |
- if err := d.store.GetObject(datastore.Key(kvObject.Key()...), kvObject); err != nil {
|
|
| 125 |
- return fmt.Errorf("could not update the kvobject to latest when trying to delete: %v", err)
|
|
| 126 |
- } |
|
| 127 |
- goto retry |
|
| 128 |
- } |
|
| 129 |
- return err |
|
| 130 |
- } |
|
| 131 |
- |
|
| 132 |
- return nil |
|
| 133 |
-} |
|
| 134 |
- |
|
| 135 |
-func (ncfg *networkConfiguration) MarshalJSON() ([]byte, error) {
|
|
| 136 |
- nMap := make(map[string]interface{})
|
|
| 137 |
- nMap["ID"] = ncfg.ID |
|
| 138 |
- nMap["BridgeName"] = ncfg.BridgeName |
|
| 139 |
- nMap["BridgeNameInternal"] = ncfg.BridgeNameInternal |
|
| 140 |
- nMap["EnableIPv6"] = ncfg.EnableIPv6 |
|
| 141 |
- nMap["EnableIPMasquerade"] = ncfg.EnableIPMasquerade |
|
| 142 |
- nMap["EnableICC"] = ncfg.EnableICC |
|
| 143 |
- nMap["Mtu"] = ncfg.Mtu |
|
| 144 |
- nMap["Internal"] = ncfg.Internal |
|
| 145 |
- nMap["DefaultBridge"] = ncfg.DefaultBridge |
|
| 146 |
- nMap["DefaultBindingIP"] = ncfg.DefaultBindingIP.String() |
|
| 147 |
- nMap["DefaultBindingIntf"] = ncfg.DefaultBindingIntf |
|
| 148 |
- nMap["DefaultGatewayIPv4"] = ncfg.DefaultGatewayIPv4.String() |
|
| 149 |
- nMap["DefaultGatewayIPv6"] = ncfg.DefaultGatewayIPv6.String() |
|
| 150 |
- |
|
| 151 |
- if ncfg.AddressIPv4 != nil {
|
|
| 152 |
- nMap["AddressIPv4"] = ncfg.AddressIPv4.String() |
|
| 153 |
- } |
|
| 154 |
- |
|
| 155 |
- if ncfg.AddressIPv6 != nil {
|
|
| 156 |
- nMap["AddressIPv6"] = ncfg.AddressIPv6.String() |
|
| 157 |
- } |
|
| 158 |
- |
|
| 159 |
- return json.Marshal(nMap) |
|
| 160 |
-} |
|
| 161 |
- |
|
| 162 |
-func (ncfg *networkConfiguration) UnmarshalJSON(b []byte) error {
|
|
| 163 |
- var ( |
|
| 164 |
- err error |
|
| 165 |
- nMap map[string]interface{}
|
|
| 166 |
- ) |
|
| 167 |
- |
|
| 168 |
- if err = json.Unmarshal(b, &nMap); err != nil {
|
|
| 169 |
- return err |
|
| 170 |
- } |
|
| 171 |
- |
|
| 172 |
- if v, ok := nMap["AddressIPv4"]; ok {
|
|
| 173 |
- if ncfg.AddressIPv4, err = types.ParseCIDR(v.(string)); err != nil {
|
|
| 174 |
- return types.InternalErrorf("failed to decode bridge network address IPv4 after json unmarshal: %s", v.(string))
|
|
| 175 |
- } |
|
| 176 |
- } |
|
| 177 |
- |
|
| 178 |
- if v, ok := nMap["AddressIPv6"]; ok {
|
|
| 179 |
- if ncfg.AddressIPv6, err = types.ParseCIDR(v.(string)); err != nil {
|
|
| 180 |
- return types.InternalErrorf("failed to decode bridge network address IPv6 after json unmarshal: %s", v.(string))
|
|
| 181 |
- } |
|
| 182 |
- } |
|
| 183 |
- |
|
| 184 |
- ncfg.DefaultBridge = nMap["DefaultBridge"].(bool) |
|
| 185 |
- ncfg.DefaultBindingIP = net.ParseIP(nMap["DefaultBindingIP"].(string)) |
|
| 186 |
- ncfg.DefaultBindingIntf = nMap["DefaultBindingIntf"].(string) |
|
| 187 |
- ncfg.DefaultGatewayIPv4 = net.ParseIP(nMap["DefaultGatewayIPv4"].(string)) |
|
| 188 |
- ncfg.DefaultGatewayIPv6 = net.ParseIP(nMap["DefaultGatewayIPv6"].(string)) |
|
| 189 |
- ncfg.ID = nMap["ID"].(string) |
|
| 190 |
- ncfg.BridgeName = nMap["BridgeName"].(string) |
|
| 191 |
- ncfg.BridgeNameInternal = nMap["BridgeNameInternal"].(string) |
|
| 192 |
- ncfg.EnableIPv6 = nMap["EnableIPv6"].(bool) |
|
| 193 |
- ncfg.EnableIPMasquerade = nMap["EnableIPMasquerade"].(bool) |
|
| 194 |
- ncfg.EnableICC = nMap["EnableICC"].(bool) |
|
| 195 |
- ncfg.Mtu = int(nMap["Mtu"].(float64)) |
|
| 196 |
- if v, ok := nMap["Internal"]; ok {
|
|
| 197 |
- ncfg.Internal = v.(bool) |
|
| 198 |
- } |
|
| 199 |
- |
|
| 200 |
- return nil |
|
| 201 |
-} |
|
| 202 |
- |
|
| 203 |
-func (ncfg *networkConfiguration) Key() []string {
|
|
| 204 |
- return []string{bridgePrefix, ncfg.ID}
|
|
| 205 |
-} |
|
| 206 |
- |
|
| 207 |
-func (ncfg *networkConfiguration) KeyPrefix() []string {
|
|
| 208 |
- return []string{bridgePrefix}
|
|
| 209 |
-} |
|
| 210 |
- |
|
| 211 |
-func (ncfg *networkConfiguration) Value() []byte {
|
|
| 212 |
- b, err := json.Marshal(ncfg) |
|
| 213 |
- if err != nil {
|
|
| 214 |
- return nil |
|
| 215 |
- } |
|
| 216 |
- return b |
|
| 217 |
-} |
|
| 218 |
- |
|
| 219 |
-func (ncfg *networkConfiguration) SetValue(value []byte) error {
|
|
| 220 |
- return json.Unmarshal(value, ncfg) |
|
| 221 |
-} |
|
| 222 |
- |
|
| 223 |
-func (ncfg *networkConfiguration) Index() uint64 {
|
|
| 224 |
- return ncfg.dbIndex |
|
| 225 |
-} |
|
| 226 |
- |
|
| 227 |
-func (ncfg *networkConfiguration) SetIndex(index uint64) {
|
|
| 228 |
- ncfg.dbIndex = index |
|
| 229 |
- ncfg.dbExists = true |
|
| 230 |
-} |
|
| 231 |
- |
|
| 232 |
-func (ncfg *networkConfiguration) Exists() bool {
|
|
| 233 |
- return ncfg.dbExists |
|
| 234 |
-} |
|
| 235 |
- |
|
| 236 |
-func (ncfg *networkConfiguration) Skip() bool {
|
|
| 237 |
- return false |
|
| 238 |
-} |
|
| 239 |
- |
|
| 240 |
-func (ncfg *networkConfiguration) New() datastore.KVObject {
|
|
| 241 |
- return &networkConfiguration{}
|
|
| 242 |
-} |
|
| 243 |
- |
|
| 244 |
-func (ncfg *networkConfiguration) CopyTo(o datastore.KVObject) error {
|
|
| 245 |
- dstNcfg := o.(*networkConfiguration) |
|
| 246 |
- *dstNcfg = *ncfg |
|
| 247 |
- return nil |
|
| 248 |
-} |
|
| 249 |
- |
|
| 250 |
-func (ncfg *networkConfiguration) DataScope() string {
|
|
| 251 |
- return datastore.LocalScope |
|
| 252 |
-} |
|
| 253 |
- |
|
| 254 |
-func (ep *bridgeEndpoint) MarshalJSON() ([]byte, error) {
|
|
| 255 |
- epMap := make(map[string]interface{})
|
|
| 256 |
- epMap["id"] = ep.id |
|
| 257 |
- epMap["nid"] = ep.nid |
|
| 258 |
- epMap["SrcName"] = ep.srcName |
|
| 259 |
- epMap["MacAddress"] = ep.macAddress.String() |
|
| 260 |
- epMap["Addr"] = ep.addr.String() |
|
| 261 |
- if ep.addrv6 != nil {
|
|
| 262 |
- epMap["Addrv6"] = ep.addrv6.String() |
|
| 263 |
- } |
|
| 264 |
- epMap["Config"] = ep.config |
|
| 265 |
- epMap["ContainerConfig"] = ep.containerConfig |
|
| 266 |
- epMap["ExternalConnConfig"] = ep.extConnConfig |
|
| 267 |
- epMap["PortMapping"] = ep.portMapping |
|
| 268 |
- |
|
| 269 |
- return json.Marshal(epMap) |
|
| 270 |
-} |
|
| 271 |
- |
|
| 272 |
-func (ep *bridgeEndpoint) UnmarshalJSON(b []byte) error {
|
|
| 273 |
- var ( |
|
| 274 |
- err error |
|
| 275 |
- epMap map[string]interface{}
|
|
| 276 |
- ) |
|
| 277 |
- |
|
| 278 |
- if err = json.Unmarshal(b, &epMap); err != nil {
|
|
| 279 |
- return fmt.Errorf("Failed to unmarshal to bridge endpoint: %v", err)
|
|
| 280 |
- } |
|
| 281 |
- |
|
| 282 |
- if v, ok := epMap["MacAddress"]; ok {
|
|
| 283 |
- if ep.macAddress, err = net.ParseMAC(v.(string)); err != nil {
|
|
| 284 |
- return types.InternalErrorf("failed to decode bridge endpoint MAC address (%s) after json unmarshal: %v", v.(string), err)
|
|
| 285 |
- } |
|
| 286 |
- } |
|
| 287 |
- if v, ok := epMap["Addr"]; ok {
|
|
| 288 |
- if ep.addr, err = types.ParseCIDR(v.(string)); err != nil {
|
|
| 289 |
- return types.InternalErrorf("failed to decode bridge endpoint IPv4 address (%s) after json unmarshal: %v", v.(string), err)
|
|
| 290 |
- } |
|
| 291 |
- } |
|
| 292 |
- if v, ok := epMap["Addrv6"]; ok {
|
|
| 293 |
- if ep.addrv6, err = types.ParseCIDR(v.(string)); err != nil {
|
|
| 294 |
- return types.InternalErrorf("failed to decode bridge endpoint IPv6 address (%s) after json unmarshal: %v", v.(string), err)
|
|
| 295 |
- } |
|
| 296 |
- } |
|
| 297 |
- ep.id = epMap["id"].(string) |
|
| 298 |
- ep.nid = epMap["nid"].(string) |
|
| 299 |
- ep.srcName = epMap["SrcName"].(string) |
|
| 300 |
- d, _ := json.Marshal(epMap["Config"]) |
|
| 301 |
- if err := json.Unmarshal(d, &ep.config); err != nil {
|
|
| 302 |
- logrus.Warnf("Failed to decode endpoint config %v", err)
|
|
| 303 |
- } |
|
| 304 |
- d, _ = json.Marshal(epMap["ContainerConfig"]) |
|
| 305 |
- if err := json.Unmarshal(d, &ep.containerConfig); err != nil {
|
|
| 306 |
- logrus.Warnf("Failed to decode endpoint container config %v", err)
|
|
| 307 |
- } |
|
| 308 |
- d, _ = json.Marshal(epMap["ExternalConnConfig"]) |
|
| 309 |
- if err := json.Unmarshal(d, &ep.extConnConfig); err != nil {
|
|
| 310 |
- logrus.Warnf("Failed to decode endpoint external connectivity configuration %v", err)
|
|
| 311 |
- } |
|
| 312 |
- d, _ = json.Marshal(epMap["PortMapping"]) |
|
| 313 |
- if err := json.Unmarshal(d, &ep.portMapping); err != nil {
|
|
| 314 |
- logrus.Warnf("Failed to decode endpoint port mapping %v", err)
|
|
| 315 |
- } |
|
| 316 |
- |
|
| 317 |
- return nil |
|
| 318 |
-} |
|
| 319 |
- |
|
| 320 |
-func (ep *bridgeEndpoint) Key() []string {
|
|
| 321 |
- return []string{bridgeEndpointPrefix, ep.id}
|
|
| 322 |
-} |
|
| 323 |
- |
|
| 324 |
-func (ep *bridgeEndpoint) KeyPrefix() []string {
|
|
| 325 |
- return []string{bridgeEndpointPrefix}
|
|
| 326 |
-} |
|
| 327 |
- |
|
| 328 |
-func (ep *bridgeEndpoint) Value() []byte {
|
|
| 329 |
- b, err := json.Marshal(ep) |
|
| 330 |
- if err != nil {
|
|
| 331 |
- return nil |
|
| 332 |
- } |
|
| 333 |
- return b |
|
| 334 |
-} |
|
| 335 |
- |
|
| 336 |
-func (ep *bridgeEndpoint) SetValue(value []byte) error {
|
|
| 337 |
- return json.Unmarshal(value, ep) |
|
| 338 |
-} |
|
| 339 |
- |
|
| 340 |
-func (ep *bridgeEndpoint) Index() uint64 {
|
|
| 341 |
- return ep.dbIndex |
|
| 342 |
-} |
|
| 343 |
- |
|
| 344 |
-func (ep *bridgeEndpoint) SetIndex(index uint64) {
|
|
| 345 |
- ep.dbIndex = index |
|
| 346 |
- ep.dbExists = true |
|
| 347 |
-} |
|
| 348 |
- |
|
| 349 |
-func (ep *bridgeEndpoint) Exists() bool {
|
|
| 350 |
- return ep.dbExists |
|
| 351 |
-} |
|
| 352 |
- |
|
| 353 |
-func (ep *bridgeEndpoint) Skip() bool {
|
|
| 354 |
- return false |
|
| 355 |
-} |
|
| 356 |
- |
|
| 357 |
-func (ep *bridgeEndpoint) New() datastore.KVObject {
|
|
| 358 |
- return &bridgeEndpoint{}
|
|
| 359 |
-} |
|
| 360 |
- |
|
| 361 |
-func (ep *bridgeEndpoint) CopyTo(o datastore.KVObject) error {
|
|
| 362 |
- dstEp := o.(*bridgeEndpoint) |
|
| 363 |
- *dstEp = *ep |
|
| 364 |
- return nil |
|
| 365 |
-} |
|
| 366 |
- |
|
| 367 |
-func (ep *bridgeEndpoint) DataScope() string {
|
|
| 368 |
- return datastore.LocalScope |
|
| 369 |
-} |
|
| 370 |
- |
|
| 371 |
-func (n *bridgeNetwork) restorePortAllocations(ep *bridgeEndpoint) {
|
|
| 372 |
- if ep.extConnConfig == nil || |
|
| 373 |
- ep.extConnConfig.ExposedPorts == nil || |
|
| 374 |
- ep.extConnConfig.PortBindings == nil {
|
|
| 375 |
- return |
|
| 376 |
- } |
|
| 377 |
- tmp := ep.extConnConfig.PortBindings |
|
| 378 |
- ep.extConnConfig.PortBindings = ep.portMapping |
|
| 379 |
- _, err := n.allocatePorts(ep, n.config.DefaultBindingIntf, n.config.DefaultBindingIP, n.driver.config.EnableUserlandProxy) |
|
| 380 |
- if err != nil {
|
|
| 381 |
- logrus.Warnf("Failed to reserve existing port mapping for endpoint %s:%v", ep.id[0:7], err)
|
|
| 382 |
- } |
|
| 383 |
- ep.extConnConfig.PortBindings = tmp |
|
| 384 |
-} |
| 385 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,119 +0,0 @@ |
| 1 |
-package bridge |
|
| 2 |
- |
|
| 3 |
-import "fmt" |
|
| 4 |
- |
|
| 5 |
-// ErrInvalidEndpointConfig error is returned when an endpoint create is attempted with an invalid endpoint configuration. |
|
| 6 |
-type ErrInvalidEndpointConfig struct{}
|
|
| 7 |
- |
|
| 8 |
-func (eiec *ErrInvalidEndpointConfig) Error() string {
|
|
| 9 |
- return "trying to create an endpoint with an invalid endpoint configuration" |
|
| 10 |
-} |
|
| 11 |
- |
|
| 12 |
-// BadRequest denotes the type of this error |
|
| 13 |
-func (eiec *ErrInvalidEndpointConfig) BadRequest() {}
|
|
| 14 |
- |
|
| 15 |
-// ErrNoIPAddr error is returned when bridge has no IPv4 address configured. |
|
| 16 |
-type ErrNoIPAddr struct{}
|
|
| 17 |
- |
|
| 18 |
-func (enip *ErrNoIPAddr) Error() string {
|
|
| 19 |
- return "bridge has no IPv4 address configured" |
|
| 20 |
-} |
|
| 21 |
- |
|
| 22 |
-// InternalError denotes the type of this error |
|
| 23 |
-func (enip *ErrNoIPAddr) InternalError() {}
|
|
| 24 |
- |
|
| 25 |
-// ErrInvalidGateway is returned when the user provided default gateway (v4/v6) is not not valid. |
|
| 26 |
-type ErrInvalidGateway struct{}
|
|
| 27 |
- |
|
| 28 |
-func (eig *ErrInvalidGateway) Error() string {
|
|
| 29 |
- return "default gateway ip must be part of the network" |
|
| 30 |
-} |
|
| 31 |
- |
|
| 32 |
-// BadRequest denotes the type of this error |
|
| 33 |
-func (eig *ErrInvalidGateway) BadRequest() {}
|
|
| 34 |
- |
|
| 35 |
-// ErrInvalidMtu is returned when the user provided MTU is not valid. |
|
| 36 |
-type ErrInvalidMtu int |
|
| 37 |
- |
|
| 38 |
-func (eim ErrInvalidMtu) Error() string {
|
|
| 39 |
- return fmt.Sprintf("invalid MTU number: %d", int(eim))
|
|
| 40 |
-} |
|
| 41 |
- |
|
| 42 |
-// BadRequest denotes the type of this error |
|
| 43 |
-func (eim ErrInvalidMtu) BadRequest() {}
|
|
| 44 |
- |
|
| 45 |
-// ErrUnsupportedAddressType is returned when the specified address type is not supported. |
|
| 46 |
-type ErrUnsupportedAddressType string |
|
| 47 |
- |
|
| 48 |
-func (uat ErrUnsupportedAddressType) Error() string {
|
|
| 49 |
- return fmt.Sprintf("unsupported address type: %s", string(uat))
|
|
| 50 |
-} |
|
| 51 |
- |
|
| 52 |
-// BadRequest denotes the type of this error |
|
| 53 |
-func (uat ErrUnsupportedAddressType) BadRequest() {}
|
|
| 54 |
- |
|
| 55 |
-// ActiveEndpointsError is returned when there are |
|
| 56 |
-// still active endpoints in the network being deleted. |
|
| 57 |
-type ActiveEndpointsError string |
|
| 58 |
- |
|
| 59 |
-func (aee ActiveEndpointsError) Error() string {
|
|
| 60 |
- return fmt.Sprintf("network %s has active endpoint", string(aee))
|
|
| 61 |
-} |
|
| 62 |
- |
|
| 63 |
-// Forbidden denotes the type of this error |
|
| 64 |
-func (aee ActiveEndpointsError) Forbidden() {}
|
|
| 65 |
- |
|
| 66 |
-// InvalidNetworkIDError is returned when the passed |
|
| 67 |
-// network id for an existing network is not a known id. |
|
| 68 |
-type InvalidNetworkIDError string |
|
| 69 |
- |
|
| 70 |
-func (inie InvalidNetworkIDError) Error() string {
|
|
| 71 |
- return fmt.Sprintf("invalid network id %s", string(inie))
|
|
| 72 |
-} |
|
| 73 |
- |
|
| 74 |
-// NotFound denotes the type of this error |
|
| 75 |
-func (inie InvalidNetworkIDError) NotFound() {}
|
|
| 76 |
- |
|
| 77 |
-// InvalidEndpointIDError is returned when the passed |
|
| 78 |
-// endpoint id is not valid. |
|
| 79 |
-type InvalidEndpointIDError string |
|
| 80 |
- |
|
| 81 |
-func (ieie InvalidEndpointIDError) Error() string {
|
|
| 82 |
- return fmt.Sprintf("invalid endpoint id: %s", string(ieie))
|
|
| 83 |
-} |
|
| 84 |
- |
|
| 85 |
-// BadRequest denotes the type of this error |
|
| 86 |
-func (ieie InvalidEndpointIDError) BadRequest() {}
|
|
| 87 |
- |
|
| 88 |
-// EndpointNotFoundError is returned when the no endpoint |
|
| 89 |
-// with the passed endpoint id is found. |
|
| 90 |
-type EndpointNotFoundError string |
|
| 91 |
- |
|
| 92 |
-func (enfe EndpointNotFoundError) Error() string {
|
|
| 93 |
- return fmt.Sprintf("endpoint not found: %s", string(enfe))
|
|
| 94 |
-} |
|
| 95 |
- |
|
| 96 |
-// NotFound denotes the type of this error |
|
| 97 |
-func (enfe EndpointNotFoundError) NotFound() {}
|
|
| 98 |
- |
|
| 99 |
-// NonDefaultBridgeExistError is returned when a non-default |
|
| 100 |
-// bridge config is passed but it does not already exist. |
|
| 101 |
-type NonDefaultBridgeExistError string |
|
| 102 |
- |
|
| 103 |
-func (ndbee NonDefaultBridgeExistError) Error() string {
|
|
| 104 |
- return fmt.Sprintf("bridge device with non default name %s must be created manually", string(ndbee))
|
|
| 105 |
-} |
|
| 106 |
- |
|
| 107 |
-// Forbidden denotes the type of this error |
|
| 108 |
-func (ndbee NonDefaultBridgeExistError) Forbidden() {}
|
|
| 109 |
- |
|
| 110 |
-// NonDefaultBridgeNeedsIPError is returned when a non-default |
|
| 111 |
-// bridge config is passed but it has no ip configured |
|
| 112 |
-type NonDefaultBridgeNeedsIPError string |
|
| 113 |
- |
|
| 114 |
-func (ndbee NonDefaultBridgeNeedsIPError) Error() string {
|
|
| 115 |
- return fmt.Sprintf("bridge device with non default name %s must have a valid IP address", string(ndbee))
|
|
| 116 |
-} |
|
| 117 |
- |
|
| 118 |
-// Forbidden denotes the type of this error |
|
| 119 |
-func (ndbee NonDefaultBridgeNeedsIPError) Forbidden() {}
|
| 120 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,225 +0,0 @@ |
| 1 |
-// +build solaris |
|
| 2 |
- |
|
| 3 |
-package bridge |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "bytes" |
|
| 7 |
- "errors" |
|
| 8 |
- "fmt" |
|
| 9 |
- "net" |
|
| 10 |
- "os" |
|
| 11 |
- "os/exec" |
|
| 12 |
- |
|
| 13 |
- "github.com/docker/libnetwork/types" |
|
| 14 |
- "github.com/sirupsen/logrus" |
|
| 15 |
-) |
|
| 16 |
- |
|
| 17 |
-var ( |
|
| 18 |
- defaultBindingIP = net.IPv4(0, 0, 0, 0) |
|
| 19 |
-) |
|
| 20 |
- |
|
| 21 |
-const ( |
|
| 22 |
- maxAllocatePortAttempts = 10 |
|
| 23 |
-) |
|
| 24 |
- |
|
| 25 |
-func addPFRules(epid, bindIntf string, bs []types.PortBinding) {
|
|
| 26 |
- var id string |
|
| 27 |
- |
|
| 28 |
- if len(epid) > 12 {
|
|
| 29 |
- id = epid[:12] |
|
| 30 |
- } else {
|
|
| 31 |
- id = epid |
|
| 32 |
- } |
|
| 33 |
- |
|
| 34 |
- fname := "/var/lib/docker/network/files/pf." + id |
|
| 35 |
- |
|
| 36 |
- f, err := os.OpenFile(fname, |
|
| 37 |
- os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) |
|
| 38 |
- if err != nil {
|
|
| 39 |
- logrus.Warn("cannot open temp pf file")
|
|
| 40 |
- return |
|
| 41 |
- } |
|
| 42 |
- for _, b := range bs {
|
|
| 43 |
- r := fmt.Sprintf( |
|
| 44 |
- "pass in on %s proto %s from any to (%s) "+ |
|
| 45 |
- "port %d rdr-to %s port %d\n", bindIntf, |
|
| 46 |
- b.Proto.String(), bindIntf, b.HostPort, |
|
| 47 |
- b.IP.String(), b.Port) |
|
| 48 |
- _, err = f.WriteString(r) |
|
| 49 |
- if err != nil {
|
|
| 50 |
- logrus.Warnf("cannot write firewall rules to %s: %v", fname, err)
|
|
| 51 |
- } |
|
| 52 |
- } |
|
| 53 |
- f.Close() |
|
| 54 |
- |
|
| 55 |
- anchor := fmt.Sprintf("_auto/docker/ep%s", id)
|
|
| 56 |
- err = exec.Command("/usr/sbin/pfctl", "-a", anchor, "-f", fname).Run()
|
|
| 57 |
- if err != nil {
|
|
| 58 |
- logrus.Warnf("failed to add firewall rules: %v", err)
|
|
| 59 |
- } |
|
| 60 |
- os.Remove(fname) |
|
| 61 |
-} |
|
| 62 |
- |
|
| 63 |
-func removePFRules(epid string) {
|
|
| 64 |
- var id string |
|
| 65 |
- |
|
| 66 |
- if len(epid) > 12 {
|
|
| 67 |
- id = epid[:12] |
|
| 68 |
- } else {
|
|
| 69 |
- id = epid |
|
| 70 |
- } |
|
| 71 |
- |
|
| 72 |
- anchor := fmt.Sprintf("_auto/docker/ep%s", id)
|
|
| 73 |
- err := exec.Command("/usr/sbin/pfctl", "-a", anchor, "-F", "all").Run()
|
|
| 74 |
- if err != nil {
|
|
| 75 |
- logrus.Warnf("failed to remove firewall rules: %v", err)
|
|
| 76 |
- } |
|
| 77 |
-} |
|
| 78 |
- |
|
| 79 |
-func (n *bridgeNetwork) allocatePorts(ep *bridgeEndpoint, bindIntf string, reqDefBindIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
|
|
| 80 |
- if ep.extConnConfig == nil || ep.extConnConfig.PortBindings == nil {
|
|
| 81 |
- return nil, nil |
|
| 82 |
- } |
|
| 83 |
- |
|
| 84 |
- defHostIP := defaultBindingIP |
|
| 85 |
- if reqDefBindIP != nil {
|
|
| 86 |
- defHostIP = reqDefBindIP |
|
| 87 |
- } |
|
| 88 |
- |
|
| 89 |
- bs, err := n.allocatePortsInternal(ep.extConnConfig.PortBindings, bindIntf, ep.addr.IP, defHostIP, ulPxyEnabled) |
|
| 90 |
- if err != nil {
|
|
| 91 |
- return nil, err |
|
| 92 |
- } |
|
| 93 |
- |
|
| 94 |
- // Add PF rules for port bindings, if any |
|
| 95 |
- if len(bs) > 0 {
|
|
| 96 |
- addPFRules(ep.id, bindIntf, bs) |
|
| 97 |
- } |
|
| 98 |
- |
|
| 99 |
- return bs, err |
|
| 100 |
-} |
|
| 101 |
- |
|
| 102 |
-func (n *bridgeNetwork) allocatePortsInternal(bindings []types.PortBinding, bindIntf string, containerIP, defHostIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
|
|
| 103 |
- bs := make([]types.PortBinding, 0, len(bindings)) |
|
| 104 |
- for _, c := range bindings {
|
|
| 105 |
- b := c.GetCopy() |
|
| 106 |
- if err := n.allocatePort(&b, containerIP, defHostIP); err != nil {
|
|
| 107 |
- // On allocation failure,release previously |
|
| 108 |
- // allocated ports. On cleanup error, just log |
|
| 109 |
- // a warning message |
|
| 110 |
- if cuErr := n.releasePortsInternal(bs); cuErr != nil {
|
|
| 111 |
- logrus.Warnf("Upon allocation failure "+
|
|
| 112 |
- "for %v, failed to clear previously "+ |
|
| 113 |
- "allocated port bindings: %v", b, cuErr) |
|
| 114 |
- } |
|
| 115 |
- return nil, err |
|
| 116 |
- } |
|
| 117 |
- bs = append(bs, b) |
|
| 118 |
- } |
|
| 119 |
- return bs, nil |
|
| 120 |
-} |
|
| 121 |
- |
|
| 122 |
-func (n *bridgeNetwork) allocatePort(bnd *types.PortBinding, containerIP, defHostIP net.IP) error {
|
|
| 123 |
- var ( |
|
| 124 |
- host net.Addr |
|
| 125 |
- err error |
|
| 126 |
- ) |
|
| 127 |
- |
|
| 128 |
- // Store the container interface address in the operational binding |
|
| 129 |
- bnd.IP = containerIP |
|
| 130 |
- |
|
| 131 |
- // Adjust the host address in the operational binding |
|
| 132 |
- if len(bnd.HostIP) == 0 {
|
|
| 133 |
- bnd.HostIP = defHostIP |
|
| 134 |
- } |
|
| 135 |
- |
|
| 136 |
- // Adjust HostPortEnd if this is not a range. |
|
| 137 |
- if bnd.HostPortEnd == 0 {
|
|
| 138 |
- bnd.HostPortEnd = bnd.HostPort |
|
| 139 |
- } |
|
| 140 |
- |
|
| 141 |
- // Construct the container side transport address |
|
| 142 |
- container, err := bnd.ContainerAddr() |
|
| 143 |
- if err != nil {
|
|
| 144 |
- return err |
|
| 145 |
- } |
|
| 146 |
- |
|
| 147 |
- // Try up to maxAllocatePortAttempts times to get a port that's |
|
| 148 |
- // not already allocated. |
|
| 149 |
- for i := 0; i < maxAllocatePortAttempts; i++ {
|
|
| 150 |
- if host, err = n.portMapper.MapRange(container, bnd.HostIP, |
|
| 151 |
- int(bnd.HostPort), int(bnd.HostPortEnd), false); err == nil {
|
|
| 152 |
- break |
|
| 153 |
- } |
|
| 154 |
- // There is no point in immediately retrying to map an |
|
| 155 |
- // explicitly chosen port. |
|
| 156 |
- if bnd.HostPort != 0 {
|
|
| 157 |
- logrus.Warnf( |
|
| 158 |
- "Failed to allocate and map port %d-%d: %s", |
|
| 159 |
- bnd.HostPort, bnd.HostPortEnd, err) |
|
| 160 |
- break |
|
| 161 |
- } |
|
| 162 |
- logrus.Warnf("Failed to allocate and map port: %s, retry: %d",
|
|
| 163 |
- err, i+1) |
|
| 164 |
- } |
|
| 165 |
- if err != nil {
|
|
| 166 |
- return err |
|
| 167 |
- } |
|
| 168 |
- |
|
| 169 |
- // Save the host port (regardless it was or not specified in the |
|
| 170 |
- // binding) |
|
| 171 |
- switch netAddr := host.(type) {
|
|
| 172 |
- case *net.TCPAddr: |
|
| 173 |
- bnd.HostPort = uint16(host.(*net.TCPAddr).Port) |
|
| 174 |
- return nil |
|
| 175 |
- case *net.UDPAddr: |
|
| 176 |
- bnd.HostPort = uint16(host.(*net.UDPAddr).Port) |
|
| 177 |
- return nil |
|
| 178 |
- default: |
|
| 179 |
- // For completeness |
|
| 180 |
- return ErrUnsupportedAddressType(fmt.Sprintf("%T", netAddr))
|
|
| 181 |
- } |
|
| 182 |
-} |
|
| 183 |
- |
|
| 184 |
-func (n *bridgeNetwork) releasePorts(ep *bridgeEndpoint) error {
|
|
| 185 |
- err := n.releasePortsInternal(ep.portMapping) |
|
| 186 |
- if err != nil {
|
|
| 187 |
- return nil |
|
| 188 |
- } |
|
| 189 |
- |
|
| 190 |
- // remove rules if there are any port mappings |
|
| 191 |
- if len(ep.portMapping) > 0 {
|
|
| 192 |
- removePFRules(ep.id) |
|
| 193 |
- } |
|
| 194 |
- |
|
| 195 |
- return nil |
|
| 196 |
- |
|
| 197 |
-} |
|
| 198 |
- |
|
| 199 |
-func (n *bridgeNetwork) releasePortsInternal(bindings []types.PortBinding) error {
|
|
| 200 |
- var errorBuf bytes.Buffer |
|
| 201 |
- |
|
| 202 |
- // Attempt to release all port bindings, do not stop on failure |
|
| 203 |
- for _, m := range bindings {
|
|
| 204 |
- if err := n.releasePort(m); err != nil {
|
|
| 205 |
- errorBuf.WriteString( |
|
| 206 |
- fmt.Sprintf( |
|
| 207 |
- "\ncould not release %v because of %v", |
|
| 208 |
- m, err)) |
|
| 209 |
- } |
|
| 210 |
- } |
|
| 211 |
- |
|
| 212 |
- if errorBuf.Len() != 0 {
|
|
| 213 |
- return errors.New(errorBuf.String()) |
|
| 214 |
- } |
|
| 215 |
- return nil |
|
| 216 |
-} |
|
| 217 |
- |
|
| 218 |
-func (n *bridgeNetwork) releasePort(bnd types.PortBinding) error {
|
|
| 219 |
- // Construct the host side transport address |
|
| 220 |
- host, err := bnd.HostAddr() |
|
| 221 |
- if err != nil {
|
|
| 222 |
- return err |
|
| 223 |
- } |
|
| 224 |
- return n.portMapper.Unmap(host) |
|
| 225 |
-} |
| 226 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,274 +0,0 @@ |
| 1 |
-package overlay |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "bytes" |
|
| 5 |
- "encoding/binary" |
|
| 6 |
- "encoding/hex" |
|
| 7 |
- "fmt" |
|
| 8 |
- "hash/fnv" |
|
| 9 |
- "net" |
|
| 10 |
- "sync" |
|
| 11 |
- |
|
| 12 |
- "github.com/docker/libnetwork/types" |
|
| 13 |
- "github.com/sirupsen/logrus" |
|
| 14 |
-) |
|
| 15 |
- |
|
| 16 |
-const ( |
|
| 17 |
- mark = uint32(0xD0C4E3) |
|
| 18 |
- timeout = 30 |
|
| 19 |
- pktExpansion = 26 // SPI(4) + SeqN(4) + IV(8) + PadLength(1) + NextHeader(1) + ICV(8) |
|
| 20 |
-) |
|
| 21 |
- |
|
| 22 |
-const ( |
|
| 23 |
- forward = iota + 1 |
|
| 24 |
- reverse |
|
| 25 |
- bidir |
|
| 26 |
-) |
|
| 27 |
- |
|
| 28 |
-type key struct {
|
|
| 29 |
- value []byte |
|
| 30 |
- tag uint32 |
|
| 31 |
-} |
|
| 32 |
- |
|
| 33 |
-func (k *key) String() string {
|
|
| 34 |
- if k != nil {
|
|
| 35 |
- return fmt.Sprintf("(key: %s, tag: 0x%x)", hex.EncodeToString(k.value)[0:5], k.tag)
|
|
| 36 |
- } |
|
| 37 |
- return "" |
|
| 38 |
-} |
|
| 39 |
- |
|
| 40 |
-type spi struct {
|
|
| 41 |
- forward int |
|
| 42 |
- reverse int |
|
| 43 |
-} |
|
| 44 |
- |
|
| 45 |
-func (s *spi) String() string {
|
|
| 46 |
- return fmt.Sprintf("SPI(FWD: 0x%x, REV: 0x%x)", uint32(s.forward), uint32(s.reverse))
|
|
| 47 |
-} |
|
| 48 |
- |
|
| 49 |
-type encrMap struct {
|
|
| 50 |
- nodes map[string][]*spi |
|
| 51 |
- sync.Mutex |
|
| 52 |
-} |
|
| 53 |
- |
|
| 54 |
-func (e *encrMap) String() string {
|
|
| 55 |
- e.Lock() |
|
| 56 |
- defer e.Unlock() |
|
| 57 |
- b := new(bytes.Buffer) |
|
| 58 |
- for k, v := range e.nodes {
|
|
| 59 |
- b.WriteString("\n")
|
|
| 60 |
- b.WriteString(k) |
|
| 61 |
- b.WriteString(":")
|
|
| 62 |
- b.WriteString("[")
|
|
| 63 |
- for _, s := range v {
|
|
| 64 |
- b.WriteString(s.String()) |
|
| 65 |
- b.WriteString(",")
|
|
| 66 |
- } |
|
| 67 |
- b.WriteString("]")
|
|
| 68 |
- |
|
| 69 |
- } |
|
| 70 |
- return b.String() |
|
| 71 |
-} |
|
| 72 |
- |
|
| 73 |
-func (d *driver) checkEncryption(nid string, rIP net.IP, vxlanID uint32, isLocal, add bool) error {
|
|
| 74 |
- logrus.Debugf("checkEncryption(%s, %v, %d, %t)", nid[0:7], rIP, vxlanID, isLocal)
|
|
| 75 |
- |
|
| 76 |
- n := d.network(nid) |
|
| 77 |
- if n == nil || !n.secure {
|
|
| 78 |
- return nil |
|
| 79 |
- } |
|
| 80 |
- |
|
| 81 |
- if len(d.keys) == 0 {
|
|
| 82 |
- return types.ForbiddenErrorf("encryption key is not present")
|
|
| 83 |
- } |
|
| 84 |
- |
|
| 85 |
- lIP := net.ParseIP(d.bindAddress) |
|
| 86 |
- aIP := net.ParseIP(d.advertiseAddress) |
|
| 87 |
- nodes := map[string]net.IP{}
|
|
| 88 |
- |
|
| 89 |
- switch {
|
|
| 90 |
- case isLocal: |
|
| 91 |
- if err := d.peerDbNetworkWalk(nid, func(pKey *peerKey, pEntry *peerEntry) bool {
|
|
| 92 |
- if !aIP.Equal(pEntry.vtep) {
|
|
| 93 |
- nodes[pEntry.vtep.String()] = pEntry.vtep |
|
| 94 |
- } |
|
| 95 |
- return false |
|
| 96 |
- }); err != nil {
|
|
| 97 |
- logrus.Warnf("Failed to retrieve list of participating nodes in overlay network %s: %v", nid[0:5], err)
|
|
| 98 |
- } |
|
| 99 |
- default: |
|
| 100 |
- if len(d.network(nid).endpoints) > 0 {
|
|
| 101 |
- nodes[rIP.String()] = rIP |
|
| 102 |
- } |
|
| 103 |
- } |
|
| 104 |
- |
|
| 105 |
- logrus.Debugf("List of nodes: %s", nodes)
|
|
| 106 |
- |
|
| 107 |
- if add {
|
|
| 108 |
- for _, rIP := range nodes {
|
|
| 109 |
- if err := setupEncryption(lIP, aIP, rIP, vxlanID, d.secMap, d.keys); err != nil {
|
|
| 110 |
- logrus.Warnf("Failed to program network encryption between %s and %s: %v", lIP, rIP, err)
|
|
| 111 |
- } |
|
| 112 |
- } |
|
| 113 |
- } else {
|
|
| 114 |
- if len(nodes) == 0 {
|
|
| 115 |
- if err := removeEncryption(lIP, rIP, d.secMap); err != nil {
|
|
| 116 |
- logrus.Warnf("Failed to remove network encryption between %s and %s: %v", lIP, rIP, err)
|
|
| 117 |
- } |
|
| 118 |
- } |
|
| 119 |
- } |
|
| 120 |
- |
|
| 121 |
- return nil |
|
| 122 |
-} |
|
| 123 |
- |
|
| 124 |
-func setupEncryption(localIP, advIP, remoteIP net.IP, vni uint32, em *encrMap, keys []*key) error {
|
|
| 125 |
- logrus.Debugf("Programming encryption for vxlan %d between %s and %s", vni, localIP, remoteIP)
|
|
| 126 |
- rIPs := remoteIP.String() |
|
| 127 |
- |
|
| 128 |
- indices := make([]*spi, 0, len(keys)) |
|
| 129 |
- |
|
| 130 |
- err := programMangle(vni, true) |
|
| 131 |
- if err != nil {
|
|
| 132 |
- logrus.Warn(err) |
|
| 133 |
- } |
|
| 134 |
- |
|
| 135 |
- em.Lock() |
|
| 136 |
- em.nodes[rIPs] = indices |
|
| 137 |
- em.Unlock() |
|
| 138 |
- |
|
| 139 |
- return nil |
|
| 140 |
-} |
|
| 141 |
- |
|
| 142 |
-func removeEncryption(localIP, remoteIP net.IP, em *encrMap) error {
|
|
| 143 |
- return nil |
|
| 144 |
-} |
|
| 145 |
- |
|
| 146 |
-func programMangle(vni uint32, add bool) (err error) {
|
|
| 147 |
- return |
|
| 148 |
-} |
|
| 149 |
- |
|
| 150 |
-func buildSPI(src, dst net.IP, st uint32) int {
|
|
| 151 |
- b := make([]byte, 4) |
|
| 152 |
- binary.BigEndian.PutUint32(b, st) |
|
| 153 |
- h := fnv.New32a() |
|
| 154 |
- h.Write(src) |
|
| 155 |
- h.Write(b) |
|
| 156 |
- h.Write(dst) |
|
| 157 |
- return int(binary.BigEndian.Uint32(h.Sum(nil))) |
|
| 158 |
-} |
|
| 159 |
- |
|
| 160 |
-func (d *driver) secMapWalk(f func(string, []*spi) ([]*spi, bool)) error {
|
|
| 161 |
- d.secMap.Lock() |
|
| 162 |
- for node, indices := range d.secMap.nodes {
|
|
| 163 |
- idxs, stop := f(node, indices) |
|
| 164 |
- if idxs != nil {
|
|
| 165 |
- d.secMap.nodes[node] = idxs |
|
| 166 |
- } |
|
| 167 |
- if stop {
|
|
| 168 |
- break |
|
| 169 |
- } |
|
| 170 |
- } |
|
| 171 |
- d.secMap.Unlock() |
|
| 172 |
- return nil |
|
| 173 |
-} |
|
| 174 |
- |
|
| 175 |
-func (d *driver) setKeys(keys []*key) error {
|
|
| 176 |
- if d.keys != nil {
|
|
| 177 |
- return types.ForbiddenErrorf("initial keys are already present")
|
|
| 178 |
- } |
|
| 179 |
- d.keys = keys |
|
| 180 |
- logrus.Debugf("Initial encryption keys: %v", d.keys)
|
|
| 181 |
- return nil |
|
| 182 |
-} |
|
| 183 |
- |
|
| 184 |
-// updateKeys allows to add a new key and/or change the primary key and/or prune an existing key |
|
| 185 |
-// The primary key is the key used in transmission and will go in first position in the list. |
|
| 186 |
-func (d *driver) updateKeys(newKey, primary, pruneKey *key) error {
|
|
| 187 |
- logrus.Debugf("Updating Keys. New: %v, Primary: %v, Pruned: %v", newKey, primary, pruneKey)
|
|
| 188 |
- |
|
| 189 |
- logrus.Debugf("Current: %v", d.keys)
|
|
| 190 |
- |
|
| 191 |
- var ( |
|
| 192 |
- newIdx = -1 |
|
| 193 |
- priIdx = -1 |
|
| 194 |
- delIdx = -1 |
|
| 195 |
- lIP = net.ParseIP(d.bindAddress) |
|
| 196 |
- ) |
|
| 197 |
- |
|
| 198 |
- d.Lock() |
|
| 199 |
- // add new |
|
| 200 |
- if newKey != nil {
|
|
| 201 |
- d.keys = append(d.keys, newKey) |
|
| 202 |
- newIdx += len(d.keys) |
|
| 203 |
- } |
|
| 204 |
- for i, k := range d.keys {
|
|
| 205 |
- if primary != nil && k.tag == primary.tag {
|
|
| 206 |
- priIdx = i |
|
| 207 |
- } |
|
| 208 |
- if pruneKey != nil && k.tag == pruneKey.tag {
|
|
| 209 |
- delIdx = i |
|
| 210 |
- } |
|
| 211 |
- } |
|
| 212 |
- d.Unlock() |
|
| 213 |
- |
|
| 214 |
- if (newKey != nil && newIdx == -1) || |
|
| 215 |
- (primary != nil && priIdx == -1) || |
|
| 216 |
- (pruneKey != nil && delIdx == -1) {
|
|
| 217 |
- err := types.BadRequestErrorf("cannot find proper key indices while processing key update:"+
|
|
| 218 |
- "(newIdx,priIdx,delIdx):(%d, %d, %d)", newIdx, priIdx, delIdx) |
|
| 219 |
- logrus.Warn(err) |
|
| 220 |
- return err |
|
| 221 |
- } |
|
| 222 |
- |
|
| 223 |
- d.secMapWalk(func(rIPs string, spis []*spi) ([]*spi, bool) {
|
|
| 224 |
- rIP := net.ParseIP(rIPs) |
|
| 225 |
- return updateNodeKey(lIP, rIP, spis, d.keys, newIdx, priIdx, delIdx), false |
|
| 226 |
- }) |
|
| 227 |
- |
|
| 228 |
- d.Lock() |
|
| 229 |
- // swap primary |
|
| 230 |
- if priIdx != -1 {
|
|
| 231 |
- swp := d.keys[0] |
|
| 232 |
- d.keys[0] = d.keys[priIdx] |
|
| 233 |
- d.keys[priIdx] = swp |
|
| 234 |
- } |
|
| 235 |
- // prune |
|
| 236 |
- if delIdx != -1 {
|
|
| 237 |
- if delIdx == 0 {
|
|
| 238 |
- delIdx = priIdx |
|
| 239 |
- } |
|
| 240 |
- d.keys = append(d.keys[:delIdx], d.keys[delIdx+1:]...) |
|
| 241 |
- } |
|
| 242 |
- d.Unlock() |
|
| 243 |
- |
|
| 244 |
- logrus.Debugf("Updated: %v", d.keys)
|
|
| 245 |
- |
|
| 246 |
- return nil |
|
| 247 |
-} |
|
| 248 |
- |
|
| 249 |
-/******************************************************** |
|
| 250 |
- * Steady state: rSA0, rSA1, rSA2, fSA1, fSP1 |
|
| 251 |
- * Rotation --> -rSA0, +rSA3, +fSA2, +fSP2/-fSP1, -fSA1 |
|
| 252 |
- * Steady state: rSA1, rSA2, rSA3, fSA2, fSP2 |
|
| 253 |
- *********************************************************/ |
|
| 254 |
- |
|
| 255 |
-// Spis and keys are sorted in such away the one in position 0 is the primary |
|
| 256 |
-func updateNodeKey(lIP, rIP net.IP, idxs []*spi, curKeys []*key, newIdx, priIdx, delIdx int) []*spi {
|
|
| 257 |
- logrus.Debugf("Updating keys for node: %s (%d,%d,%d)", rIP, newIdx, priIdx, delIdx)
|
|
| 258 |
- return nil |
|
| 259 |
-} |
|
| 260 |
- |
|
| 261 |
-func (n *network) maxMTU() int {
|
|
| 262 |
- mtu := 1500 |
|
| 263 |
- if n.mtu != 0 {
|
|
| 264 |
- mtu = n.mtu |
|
| 265 |
- } |
|
| 266 |
- mtu -= vxlanEncap |
|
| 267 |
- if n.secure {
|
|
| 268 |
- // In case of encryption account for the |
|
| 269 |
- // esp packet espansion and padding |
|
| 270 |
- mtu -= pktExpansion |
|
| 271 |
- mtu -= (mtu % 4) |
|
| 272 |
- } |
|
| 273 |
- return mtu |
|
| 274 |
-} |
| 275 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,188 +0,0 @@ |
| 1 |
-package overlay |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "net" |
|
| 6 |
- |
|
| 7 |
- "github.com/docker/libnetwork/driverapi" |
|
| 8 |
- "github.com/docker/libnetwork/types" |
|
| 9 |
- "github.com/gogo/protobuf/proto" |
|
| 10 |
- "github.com/sirupsen/logrus" |
|
| 11 |
-) |
|
| 12 |
- |
|
| 13 |
-// Join method is invoked when a Sandbox is attached to an endpoint. |
|
| 14 |
-func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
|
| 15 |
- if err := validateID(nid, eid); err != nil {
|
|
| 16 |
- return err |
|
| 17 |
- } |
|
| 18 |
- |
|
| 19 |
- n := d.network(nid) |
|
| 20 |
- if n == nil {
|
|
| 21 |
- return fmt.Errorf("could not find network with id %s", nid)
|
|
| 22 |
- } |
|
| 23 |
- |
|
| 24 |
- ep := n.endpoint(eid) |
|
| 25 |
- if ep == nil {
|
|
| 26 |
- return fmt.Errorf("could not find endpoint with id %s", eid)
|
|
| 27 |
- } |
|
| 28 |
- |
|
| 29 |
- if n.secure && len(d.keys) == 0 {
|
|
| 30 |
- return fmt.Errorf("cannot join secure network: encryption keys not present")
|
|
| 31 |
- } |
|
| 32 |
- |
|
| 33 |
- s := n.getSubnetforIP(ep.addr) |
|
| 34 |
- if s == nil {
|
|
| 35 |
- return fmt.Errorf("could not find subnet for endpoint %s", eid)
|
|
| 36 |
- } |
|
| 37 |
- |
|
| 38 |
- if err := n.obtainVxlanID(s); err != nil {
|
|
| 39 |
- return fmt.Errorf("couldn't get vxlan id for %q: %v", s.subnetIP.String(), err)
|
|
| 40 |
- } |
|
| 41 |
- |
|
| 42 |
- if err := n.joinSandbox(false); err != nil {
|
|
| 43 |
- return fmt.Errorf("network sandbox join failed: %v", err)
|
|
| 44 |
- } |
|
| 45 |
- |
|
| 46 |
- if err := n.joinSubnetSandbox(s, false); err != nil {
|
|
| 47 |
- return fmt.Errorf("subnet sandbox join failed for %q: %v", s.subnetIP.String(), err)
|
|
| 48 |
- } |
|
| 49 |
- |
|
| 50 |
- // joinSubnetSandbox gets called when an endpoint comes up on a new subnet in the |
|
| 51 |
- // overlay network. Hence the Endpoint count should be updated outside joinSubnetSandbox |
|
| 52 |
- n.incEndpointCount() |
|
| 53 |
- |
|
| 54 |
- // Add creating a veth Pair for Solaris |
|
| 55 |
- |
|
| 56 |
- containerIfName := "solaris-if" |
|
| 57 |
- ep.ifName = containerIfName |
|
| 58 |
- |
|
| 59 |
- if err := d.writeEndpointToStore(ep); err != nil {
|
|
| 60 |
- return fmt.Errorf("failed to update overlay endpoint %s to local data store: %v", ep.id[0:7], err)
|
|
| 61 |
- } |
|
| 62 |
- |
|
| 63 |
- // Add solaris plumbing to add veth (with ep mac addr) to sandbox |
|
| 64 |
- |
|
| 65 |
- for _, sub := range n.subnets {
|
|
| 66 |
- if sub == s {
|
|
| 67 |
- continue |
|
| 68 |
- } |
|
| 69 |
- if err := jinfo.AddStaticRoute(sub.subnetIP, types.NEXTHOP, s.gwIP.IP); err != nil {
|
|
| 70 |
- logrus.Errorf("Adding subnet %s static route in network %q failed\n", s.subnetIP, n.id)
|
|
| 71 |
- } |
|
| 72 |
- } |
|
| 73 |
- |
|
| 74 |
- if iNames := jinfo.InterfaceName(); iNames != nil {
|
|
| 75 |
- err := iNames.SetNames(containerIfName, "eth") |
|
| 76 |
- if err != nil {
|
|
| 77 |
- return err |
|
| 78 |
- } |
|
| 79 |
- } |
|
| 80 |
- |
|
| 81 |
- d.peerDbAdd(nid, eid, ep.addr.IP, ep.addr.Mask, ep.mac, |
|
| 82 |
- net.ParseIP(d.advertiseAddress), true) |
|
| 83 |
- |
|
| 84 |
- if err := d.checkEncryption(nid, nil, n.vxlanID(s), true, true); err != nil {
|
|
| 85 |
- logrus.Warn(err) |
|
| 86 |
- } |
|
| 87 |
- |
|
| 88 |
- buf, err := proto.Marshal(&PeerRecord{
|
|
| 89 |
- EndpointIP: ep.addr.String(), |
|
| 90 |
- EndpointMAC: ep.mac.String(), |
|
| 91 |
- TunnelEndpointIP: d.advertiseAddress, |
|
| 92 |
- }) |
|
| 93 |
- if err != nil {
|
|
| 94 |
- return err |
|
| 95 |
- } |
|
| 96 |
- |
|
| 97 |
- if err := jinfo.AddTableEntry(ovPeerTable, eid, buf); err != nil {
|
|
| 98 |
- logrus.Errorf("overlay: Failed adding table entry to joininfo: %v", err)
|
|
| 99 |
- } |
|
| 100 |
- |
|
| 101 |
- d.pushLocalEndpointEvent("join", nid, eid)
|
|
| 102 |
- |
|
| 103 |
- return nil |
|
| 104 |
-} |
|
| 105 |
- |
|
| 106 |
-func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
|
|
| 107 |
- if tableName != ovPeerTable {
|
|
| 108 |
- logrus.Errorf("Unexpected table notification for table %s received", tableName)
|
|
| 109 |
- return |
|
| 110 |
- } |
|
| 111 |
- |
|
| 112 |
- eid := key |
|
| 113 |
- |
|
| 114 |
- var peer PeerRecord |
|
| 115 |
- if err := proto.Unmarshal(value, &peer); err != nil {
|
|
| 116 |
- logrus.Errorf("Failed to unmarshal peer record: %v", err)
|
|
| 117 |
- return |
|
| 118 |
- } |
|
| 119 |
- |
|
| 120 |
- // Ignore local peers. We already know about them and they |
|
| 121 |
- // should not be added to vxlan fdb. |
|
| 122 |
- if peer.TunnelEndpointIP == d.advertiseAddress {
|
|
| 123 |
- return |
|
| 124 |
- } |
|
| 125 |
- |
|
| 126 |
- addr, err := types.ParseCIDR(peer.EndpointIP) |
|
| 127 |
- if err != nil {
|
|
| 128 |
- logrus.Errorf("Invalid peer IP %s received in event notify", peer.EndpointIP)
|
|
| 129 |
- return |
|
| 130 |
- } |
|
| 131 |
- |
|
| 132 |
- mac, err := net.ParseMAC(peer.EndpointMAC) |
|
| 133 |
- if err != nil {
|
|
| 134 |
- logrus.Errorf("Invalid mac %s received in event notify", peer.EndpointMAC)
|
|
| 135 |
- return |
|
| 136 |
- } |
|
| 137 |
- |
|
| 138 |
- vtep := net.ParseIP(peer.TunnelEndpointIP) |
|
| 139 |
- if vtep == nil {
|
|
| 140 |
- logrus.Errorf("Invalid VTEP %s received in event notify", peer.TunnelEndpointIP)
|
|
| 141 |
- return |
|
| 142 |
- } |
|
| 143 |
- |
|
| 144 |
- if etype == driverapi.Delete {
|
|
| 145 |
- d.peerDelete(nid, eid, addr.IP, addr.Mask, mac, vtep, true) |
|
| 146 |
- return |
|
| 147 |
- } |
|
| 148 |
- |
|
| 149 |
- d.peerAdd(nid, eid, addr.IP, addr.Mask, mac, vtep, true) |
|
| 150 |
-} |
|
| 151 |
- |
|
| 152 |
-func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
|
|
| 153 |
- return "", nil |
|
| 154 |
-} |
|
| 155 |
- |
|
| 156 |
-// Leave method is invoked when a Sandbox detaches from an endpoint. |
|
| 157 |
-func (d *driver) Leave(nid, eid string) error {
|
|
| 158 |
- if err := validateID(nid, eid); err != nil {
|
|
| 159 |
- return err |
|
| 160 |
- } |
|
| 161 |
- |
|
| 162 |
- n := d.network(nid) |
|
| 163 |
- if n == nil {
|
|
| 164 |
- return fmt.Errorf("could not find network with id %s", nid)
|
|
| 165 |
- } |
|
| 166 |
- |
|
| 167 |
- ep := n.endpoint(eid) |
|
| 168 |
- |
|
| 169 |
- if ep == nil {
|
|
| 170 |
- return types.InternalMaskableErrorf("could not find endpoint with id %s", eid)
|
|
| 171 |
- } |
|
| 172 |
- |
|
| 173 |
- if d.notifyCh != nil {
|
|
| 174 |
- d.notifyCh <- ovNotify{
|
|
| 175 |
- action: "leave", |
|
| 176 |
- nw: n, |
|
| 177 |
- ep: ep, |
|
| 178 |
- } |
|
| 179 |
- } |
|
| 180 |
- |
|
| 181 |
- n.leaveSandbox() |
|
| 182 |
- |
|
| 183 |
- if err := d.checkEncryption(nid, nil, 0, true, false); err != nil {
|
|
| 184 |
- logrus.Warn(err) |
|
| 185 |
- } |
|
| 186 |
- |
|
| 187 |
- return nil |
|
| 188 |
-} |
| 189 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,242 +0,0 @@ |
| 1 |
-package overlay |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "encoding/json" |
|
| 5 |
- "fmt" |
|
| 6 |
- "net" |
|
| 7 |
- |
|
| 8 |
- "github.com/docker/libnetwork/datastore" |
|
| 9 |
- "github.com/docker/libnetwork/driverapi" |
|
| 10 |
- "github.com/docker/libnetwork/netutils" |
|
| 11 |
- "github.com/docker/libnetwork/types" |
|
| 12 |
- "github.com/sirupsen/logrus" |
|
| 13 |
-) |
|
| 14 |
- |
|
| 15 |
-type endpointTable map[string]*endpoint |
|
| 16 |
- |
|
| 17 |
-const overlayEndpointPrefix = "overlay/endpoint" |
|
| 18 |
- |
|
| 19 |
-type endpoint struct {
|
|
| 20 |
- id string |
|
| 21 |
- nid string |
|
| 22 |
- ifName string |
|
| 23 |
- mac net.HardwareAddr |
|
| 24 |
- addr *net.IPNet |
|
| 25 |
- dbExists bool |
|
| 26 |
- dbIndex uint64 |
|
| 27 |
-} |
|
| 28 |
- |
|
| 29 |
-func (n *network) endpoint(eid string) *endpoint {
|
|
| 30 |
- n.Lock() |
|
| 31 |
- defer n.Unlock() |
|
| 32 |
- |
|
| 33 |
- return n.endpoints[eid] |
|
| 34 |
-} |
|
| 35 |
- |
|
| 36 |
-func (n *network) addEndpoint(ep *endpoint) {
|
|
| 37 |
- n.Lock() |
|
| 38 |
- n.endpoints[ep.id] = ep |
|
| 39 |
- n.Unlock() |
|
| 40 |
-} |
|
| 41 |
- |
|
| 42 |
-func (n *network) deleteEndpoint(eid string) {
|
|
| 43 |
- n.Lock() |
|
| 44 |
- delete(n.endpoints, eid) |
|
| 45 |
- n.Unlock() |
|
| 46 |
-} |
|
| 47 |
- |
|
| 48 |
-func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, |
|
| 49 |
- epOptions map[string]interface{}) error {
|
|
| 50 |
- var err error |
|
| 51 |
- |
|
| 52 |
- if err = validateID(nid, eid); err != nil {
|
|
| 53 |
- return err |
|
| 54 |
- } |
|
| 55 |
- |
|
| 56 |
- // Since we perform lazy configuration make sure we try |
|
| 57 |
- // configuring the driver when we enter CreateEndpoint since |
|
| 58 |
- // CreateNetwork may not be called in every node. |
|
| 59 |
- if err := d.configure(); err != nil {
|
|
| 60 |
- return err |
|
| 61 |
- } |
|
| 62 |
- |
|
| 63 |
- n := d.network(nid) |
|
| 64 |
- if n == nil {
|
|
| 65 |
- return fmt.Errorf("network id %q not found", nid)
|
|
| 66 |
- } |
|
| 67 |
- |
|
| 68 |
- ep := &endpoint{
|
|
| 69 |
- id: eid, |
|
| 70 |
- nid: n.id, |
|
| 71 |
- addr: ifInfo.Address(), |
|
| 72 |
- mac: ifInfo.MacAddress(), |
|
| 73 |
- } |
|
| 74 |
- if ep.addr == nil {
|
|
| 75 |
- return fmt.Errorf("create endpoint was not passed interface IP address")
|
|
| 76 |
- } |
|
| 77 |
- |
|
| 78 |
- if s := n.getSubnetforIP(ep.addr); s == nil {
|
|
| 79 |
- return fmt.Errorf("no matching subnet for IP %q in network %q", ep.addr, nid)
|
|
| 80 |
- } |
|
| 81 |
- |
|
| 82 |
- if ep.mac == nil {
|
|
| 83 |
- ep.mac = netutils.GenerateMACFromIP(ep.addr.IP) |
|
| 84 |
- if err := ifInfo.SetMacAddress(ep.mac); err != nil {
|
|
| 85 |
- return err |
|
| 86 |
- } |
|
| 87 |
- } |
|
| 88 |
- |
|
| 89 |
- n.addEndpoint(ep) |
|
| 90 |
- |
|
| 91 |
- if err := d.writeEndpointToStore(ep); err != nil {
|
|
| 92 |
- return fmt.Errorf("failed to update overlay endpoint %s to local store: %v", ep.id[0:7], err)
|
|
| 93 |
- } |
|
| 94 |
- |
|
| 95 |
- return nil |
|
| 96 |
-} |
|
| 97 |
- |
|
| 98 |
-func (d *driver) DeleteEndpoint(nid, eid string) error {
|
|
| 99 |
- if err := validateID(nid, eid); err != nil {
|
|
| 100 |
- return err |
|
| 101 |
- } |
|
| 102 |
- |
|
| 103 |
- n := d.network(nid) |
|
| 104 |
- if n == nil {
|
|
| 105 |
- return fmt.Errorf("network id %q not found", nid)
|
|
| 106 |
- } |
|
| 107 |
- |
|
| 108 |
- ep := n.endpoint(eid) |
|
| 109 |
- if ep == nil {
|
|
| 110 |
- return fmt.Errorf("endpoint id %q not found", eid)
|
|
| 111 |
- } |
|
| 112 |
- |
|
| 113 |
- n.deleteEndpoint(eid) |
|
| 114 |
- |
|
| 115 |
- if err := d.deleteEndpointFromStore(ep); err != nil {
|
|
| 116 |
- logrus.Warnf("Failed to delete overlay endpoint %s from local store: %v", ep.id[0:7], err)
|
|
| 117 |
- } |
|
| 118 |
- |
|
| 119 |
- if ep.ifName == "" {
|
|
| 120 |
- return nil |
|
| 121 |
- } |
|
| 122 |
- |
|
| 123 |
- // OVERLAY_SOLARIS: Add Solaris unplumbing for removing the interface endpoint |
|
| 124 |
- |
|
| 125 |
- return nil |
|
| 126 |
-} |
|
| 127 |
- |
|
| 128 |
-func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
|
|
| 129 |
- return make(map[string]interface{}, 0), nil
|
|
| 130 |
-} |
|
| 131 |
- |
|
| 132 |
-func (d *driver) deleteEndpointFromStore(e *endpoint) error {
|
|
| 133 |
- if d.localStore == nil {
|
|
| 134 |
- return fmt.Errorf("overlay local store not initialized, ep not deleted")
|
|
| 135 |
- } |
|
| 136 |
- |
|
| 137 |
- return d.localStore.DeleteObjectAtomic(e) |
|
| 138 |
-} |
|
| 139 |
- |
|
| 140 |
-func (d *driver) writeEndpointToStore(e *endpoint) error {
|
|
| 141 |
- if d.localStore == nil {
|
|
| 142 |
- return fmt.Errorf("overlay local store not initialized, ep not added")
|
|
| 143 |
- } |
|
| 144 |
- |
|
| 145 |
- return d.localStore.PutObjectAtomic(e) |
|
| 146 |
-} |
|
| 147 |
- |
|
| 148 |
-func (ep *endpoint) DataScope() string {
|
|
| 149 |
- return datastore.LocalScope |
|
| 150 |
-} |
|
| 151 |
- |
|
| 152 |
-func (ep *endpoint) New() datastore.KVObject {
|
|
| 153 |
- return &endpoint{}
|
|
| 154 |
-} |
|
| 155 |
- |
|
| 156 |
-func (ep *endpoint) CopyTo(o datastore.KVObject) error {
|
|
| 157 |
- dstep := o.(*endpoint) |
|
| 158 |
- *dstep = *ep |
|
| 159 |
- return nil |
|
| 160 |
-} |
|
| 161 |
- |
|
| 162 |
-func (ep *endpoint) Key() []string {
|
|
| 163 |
- return []string{overlayEndpointPrefix, ep.id}
|
|
| 164 |
-} |
|
| 165 |
- |
|
| 166 |
-func (ep *endpoint) KeyPrefix() []string {
|
|
| 167 |
- return []string{overlayEndpointPrefix}
|
|
| 168 |
-} |
|
| 169 |
- |
|
| 170 |
-func (ep *endpoint) Index() uint64 {
|
|
| 171 |
- return ep.dbIndex |
|
| 172 |
-} |
|
| 173 |
- |
|
| 174 |
-func (ep *endpoint) SetIndex(index uint64) {
|
|
| 175 |
- ep.dbIndex = index |
|
| 176 |
- ep.dbExists = true |
|
| 177 |
-} |
|
| 178 |
- |
|
| 179 |
-func (ep *endpoint) Exists() bool {
|
|
| 180 |
- return ep.dbExists |
|
| 181 |
-} |
|
| 182 |
- |
|
| 183 |
-func (ep *endpoint) Skip() bool {
|
|
| 184 |
- return false |
|
| 185 |
-} |
|
| 186 |
- |
|
| 187 |
-func (ep *endpoint) Value() []byte {
|
|
| 188 |
- b, err := json.Marshal(ep) |
|
| 189 |
- if err != nil {
|
|
| 190 |
- return nil |
|
| 191 |
- } |
|
| 192 |
- return b |
|
| 193 |
-} |
|
| 194 |
- |
|
| 195 |
-func (ep *endpoint) SetValue(value []byte) error {
|
|
| 196 |
- return json.Unmarshal(value, ep) |
|
| 197 |
-} |
|
| 198 |
- |
|
| 199 |
-func (ep *endpoint) MarshalJSON() ([]byte, error) {
|
|
| 200 |
- epMap := make(map[string]interface{})
|
|
| 201 |
- |
|
| 202 |
- epMap["id"] = ep.id |
|
| 203 |
- epMap["nid"] = ep.nid |
|
| 204 |
- if ep.ifName != "" {
|
|
| 205 |
- epMap["ifName"] = ep.ifName |
|
| 206 |
- } |
|
| 207 |
- if ep.addr != nil {
|
|
| 208 |
- epMap["addr"] = ep.addr.String() |
|
| 209 |
- } |
|
| 210 |
- if len(ep.mac) != 0 {
|
|
| 211 |
- epMap["mac"] = ep.mac.String() |
|
| 212 |
- } |
|
| 213 |
- |
|
| 214 |
- return json.Marshal(epMap) |
|
| 215 |
-} |
|
| 216 |
- |
|
| 217 |
-func (ep *endpoint) UnmarshalJSON(value []byte) error {
|
|
| 218 |
- var ( |
|
| 219 |
- err error |
|
| 220 |
- epMap map[string]interface{}
|
|
| 221 |
- ) |
|
| 222 |
- |
|
| 223 |
- json.Unmarshal(value, &epMap) |
|
| 224 |
- |
|
| 225 |
- ep.id = epMap["id"].(string) |
|
| 226 |
- ep.nid = epMap["nid"].(string) |
|
| 227 |
- if v, ok := epMap["mac"]; ok {
|
|
| 228 |
- if ep.mac, err = net.ParseMAC(v.(string)); err != nil {
|
|
| 229 |
- return types.InternalErrorf("failed to decode endpoint interface mac address after json unmarshal: %s", v.(string))
|
|
| 230 |
- } |
|
| 231 |
- } |
|
| 232 |
- if v, ok := epMap["addr"]; ok {
|
|
| 233 |
- if ep.addr, err = types.ParseCIDR(v.(string)); err != nil {
|
|
| 234 |
- return types.InternalErrorf("failed to decode endpoint interface ipv4 address after json unmarshal: %v", err)
|
|
| 235 |
- } |
|
| 236 |
- } |
|
| 237 |
- if v, ok := epMap["ifName"]; ok {
|
|
| 238 |
- ep.ifName = v.(string) |
|
| 239 |
- } |
|
| 240 |
- |
|
| 241 |
- return nil |
|
| 242 |
-} |
| 243 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,786 +0,0 @@ |
| 1 |
-package overlay |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "encoding/json" |
|
| 5 |
- "fmt" |
|
| 6 |
- "net" |
|
| 7 |
- "os" |
|
| 8 |
- "path/filepath" |
|
| 9 |
- "strconv" |
|
| 10 |
- "strings" |
|
| 11 |
- "sync" |
|
| 12 |
- |
|
| 13 |
- "github.com/docker/libnetwork/datastore" |
|
| 14 |
- "github.com/docker/libnetwork/driverapi" |
|
| 15 |
- "github.com/docker/libnetwork/netlabel" |
|
| 16 |
- "github.com/docker/libnetwork/netutils" |
|
| 17 |
- "github.com/docker/libnetwork/osl" |
|
| 18 |
- "github.com/docker/libnetwork/resolvconf" |
|
| 19 |
- "github.com/docker/libnetwork/types" |
|
| 20 |
- "github.com/sirupsen/logrus" |
|
| 21 |
-) |
|
| 22 |
- |
|
| 23 |
-var ( |
|
| 24 |
- hostMode bool |
|
| 25 |
- networkOnce sync.Once |
|
| 26 |
- networkMu sync.Mutex |
|
| 27 |
- vniTbl = make(map[uint32]string) |
|
| 28 |
-) |
|
| 29 |
- |
|
| 30 |
-type networkTable map[string]*network |
|
| 31 |
- |
|
| 32 |
-type subnet struct {
|
|
| 33 |
- once *sync.Once |
|
| 34 |
- vxlanName string |
|
| 35 |
- brName string |
|
| 36 |
- vni uint32 |
|
| 37 |
- initErr error |
|
| 38 |
- subnetIP *net.IPNet |
|
| 39 |
- gwIP *net.IPNet |
|
| 40 |
-} |
|
| 41 |
- |
|
| 42 |
-type subnetJSON struct {
|
|
| 43 |
- SubnetIP string |
|
| 44 |
- GwIP string |
|
| 45 |
- Vni uint32 |
|
| 46 |
-} |
|
| 47 |
- |
|
| 48 |
-type network struct {
|
|
| 49 |
- id string |
|
| 50 |
- dbIndex uint64 |
|
| 51 |
- dbExists bool |
|
| 52 |
- sbox osl.Sandbox |
|
| 53 |
- endpoints endpointTable |
|
| 54 |
- driver *driver |
|
| 55 |
- joinCnt int |
|
| 56 |
- once *sync.Once |
|
| 57 |
- initEpoch int |
|
| 58 |
- initErr error |
|
| 59 |
- subnets []*subnet |
|
| 60 |
- secure bool |
|
| 61 |
- mtu int |
|
| 62 |
- sync.Mutex |
|
| 63 |
-} |
|
| 64 |
- |
|
| 65 |
-func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
|
|
| 66 |
- return nil, types.NotImplementedErrorf("not implemented")
|
|
| 67 |
-} |
|
| 68 |
- |
|
| 69 |
-func (d *driver) NetworkFree(id string) error {
|
|
| 70 |
- return types.NotImplementedErrorf("not implemented")
|
|
| 71 |
-} |
|
| 72 |
- |
|
| 73 |
-func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
|
|
| 74 |
- if id == "" {
|
|
| 75 |
- return fmt.Errorf("invalid network id")
|
|
| 76 |
- } |
|
| 77 |
- if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" {
|
|
| 78 |
- return types.BadRequestErrorf("ipv4 pool is empty")
|
|
| 79 |
- } |
|
| 80 |
- |
|
| 81 |
- // Since we perform lazy configuration make sure we try |
|
| 82 |
- // configuring the driver when we enter CreateNetwork |
|
| 83 |
- if err := d.configure(); err != nil {
|
|
| 84 |
- return err |
|
| 85 |
- } |
|
| 86 |
- |
|
| 87 |
- n := &network{
|
|
| 88 |
- id: id, |
|
| 89 |
- driver: d, |
|
| 90 |
- endpoints: endpointTable{},
|
|
| 91 |
- once: &sync.Once{},
|
|
| 92 |
- subnets: []*subnet{},
|
|
| 93 |
- } |
|
| 94 |
- |
|
| 95 |
- vnis := make([]uint32, 0, len(ipV4Data)) |
|
| 96 |
- if gval, ok := option[netlabel.GenericData]; ok {
|
|
| 97 |
- optMap := gval.(map[string]string) |
|
| 98 |
- if val, ok := optMap[netlabel.OverlayVxlanIDList]; ok {
|
|
| 99 |
- logrus.Debugf("overlay: Received vxlan IDs: %s", val)
|
|
| 100 |
- vniStrings := strings.Split(val, ",") |
|
| 101 |
- for _, vniStr := range vniStrings {
|
|
| 102 |
- vni, err := strconv.Atoi(vniStr) |
|
| 103 |
- if err != nil {
|
|
| 104 |
- return fmt.Errorf("invalid vxlan id value %q passed", vniStr)
|
|
| 105 |
- } |
|
| 106 |
- |
|
| 107 |
- vnis = append(vnis, uint32(vni)) |
|
| 108 |
- } |
|
| 109 |
- } |
|
| 110 |
- if _, ok := optMap[secureOption]; ok {
|
|
| 111 |
- n.secure = true |
|
| 112 |
- } |
|
| 113 |
- if val, ok := optMap[netlabel.DriverMTU]; ok {
|
|
| 114 |
- var err error |
|
| 115 |
- if n.mtu, err = strconv.Atoi(val); err != nil {
|
|
| 116 |
- return fmt.Errorf("failed to parse %v: %v", val, err)
|
|
| 117 |
- } |
|
| 118 |
- if n.mtu < 0 {
|
|
| 119 |
- return fmt.Errorf("invalid MTU value: %v", n.mtu)
|
|
| 120 |
- } |
|
| 121 |
- } |
|
| 122 |
- } |
|
| 123 |
- |
|
| 124 |
- // If we are getting vnis from libnetwork, either we get for |
|
| 125 |
- // all subnets or none. |
|
| 126 |
- if len(vnis) != 0 && len(vnis) < len(ipV4Data) {
|
|
| 127 |
- return fmt.Errorf("insufficient vnis(%d) passed to overlay", len(vnis))
|
|
| 128 |
- } |
|
| 129 |
- |
|
| 130 |
- for i, ipd := range ipV4Data {
|
|
| 131 |
- s := &subnet{
|
|
| 132 |
- subnetIP: ipd.Pool, |
|
| 133 |
- gwIP: ipd.Gateway, |
|
| 134 |
- once: &sync.Once{},
|
|
| 135 |
- } |
|
| 136 |
- |
|
| 137 |
- if len(vnis) != 0 {
|
|
| 138 |
- s.vni = vnis[i] |
|
| 139 |
- } |
|
| 140 |
- |
|
| 141 |
- n.subnets = append(n.subnets, s) |
|
| 142 |
- } |
|
| 143 |
- |
|
| 144 |
- if err := n.writeToStore(); err != nil {
|
|
| 145 |
- return fmt.Errorf("failed to update data store for network %v: %v", n.id, err)
|
|
| 146 |
- } |
|
| 147 |
- |
|
| 148 |
- // Make sure no rule is on the way from any stale secure network |
|
| 149 |
- if !n.secure {
|
|
| 150 |
- for _, vni := range vnis {
|
|
| 151 |
- programMangle(vni, false) |
|
| 152 |
- } |
|
| 153 |
- } |
|
| 154 |
- |
|
| 155 |
- if nInfo != nil {
|
|
| 156 |
- if err := nInfo.TableEventRegister(ovPeerTable, driverapi.EndpointObject); err != nil {
|
|
| 157 |
- return err |
|
| 158 |
- } |
|
| 159 |
- } |
|
| 160 |
- |
|
| 161 |
- d.addNetwork(n) |
|
| 162 |
- return nil |
|
| 163 |
-} |
|
| 164 |
- |
|
| 165 |
-func (d *driver) DeleteNetwork(nid string) error {
|
|
| 166 |
- if nid == "" {
|
|
| 167 |
- return fmt.Errorf("invalid network id")
|
|
| 168 |
- } |
|
| 169 |
- |
|
| 170 |
- // Make sure driver resources are initialized before proceeding |
|
| 171 |
- if err := d.configure(); err != nil {
|
|
| 172 |
- return err |
|
| 173 |
- } |
|
| 174 |
- |
|
| 175 |
- n := d.network(nid) |
|
| 176 |
- if n == nil {
|
|
| 177 |
- return fmt.Errorf("could not find network with id %s", nid)
|
|
| 178 |
- } |
|
| 179 |
- |
|
| 180 |
- d.deleteNetwork(nid) |
|
| 181 |
- |
|
| 182 |
- vnis, err := n.releaseVxlanID() |
|
| 183 |
- if err != nil {
|
|
| 184 |
- return err |
|
| 185 |
- } |
|
| 186 |
- |
|
| 187 |
- if n.secure {
|
|
| 188 |
- for _, vni := range vnis {
|
|
| 189 |
- programMangle(vni, false) |
|
| 190 |
- } |
|
| 191 |
- } |
|
| 192 |
- |
|
| 193 |
- return nil |
|
| 194 |
-} |
|
| 195 |
- |
|
| 196 |
-func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
|
| 197 |
- return nil |
|
| 198 |
-} |
|
| 199 |
- |
|
| 200 |
-func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
|
| 201 |
- return nil |
|
| 202 |
-} |
|
| 203 |
- |
|
| 204 |
-func (n *network) incEndpointCount() {
|
|
| 205 |
- n.Lock() |
|
| 206 |
- defer n.Unlock() |
|
| 207 |
- n.joinCnt++ |
|
| 208 |
-} |
|
| 209 |
- |
|
| 210 |
-func (n *network) joinSandbox(restore bool) error {
|
|
| 211 |
- // If there is a race between two go routines here only one will win |
|
| 212 |
- // the other will wait. |
|
| 213 |
- n.once.Do(func() {
|
|
| 214 |
- // save the error status of initSandbox in n.initErr so that |
|
| 215 |
- // all the racing go routines are able to know the status. |
|
| 216 |
- n.initErr = n.initSandbox(restore) |
|
| 217 |
- }) |
|
| 218 |
- |
|
| 219 |
- return n.initErr |
|
| 220 |
-} |
|
| 221 |
- |
|
| 222 |
-func (n *network) joinSubnetSandbox(s *subnet, restore bool) error {
|
|
| 223 |
- s.once.Do(func() {
|
|
| 224 |
- s.initErr = n.initSubnetSandbox(s, restore) |
|
| 225 |
- }) |
|
| 226 |
- return s.initErr |
|
| 227 |
-} |
|
| 228 |
- |
|
| 229 |
-func (n *network) leaveSandbox() {
|
|
| 230 |
- n.Lock() |
|
| 231 |
- defer n.Unlock() |
|
| 232 |
- n.joinCnt-- |
|
| 233 |
- if n.joinCnt != 0 {
|
|
| 234 |
- return |
|
| 235 |
- } |
|
| 236 |
- |
|
| 237 |
- // We are about to destroy sandbox since the container is leaving the network |
|
| 238 |
- // Reinitialize the once variable so that we will be able to trigger one time |
|
| 239 |
- // sandbox initialization(again) when another container joins subsequently. |
|
| 240 |
- n.once = &sync.Once{}
|
|
| 241 |
- for _, s := range n.subnets {
|
|
| 242 |
- s.once = &sync.Once{}
|
|
| 243 |
- } |
|
| 244 |
- |
|
| 245 |
- n.destroySandbox() |
|
| 246 |
-} |
|
| 247 |
- |
|
| 248 |
-// to be called while holding network lock |
|
| 249 |
-func (n *network) destroySandbox() {
|
|
| 250 |
- if n.sbox != nil {
|
|
| 251 |
- for _, iface := range n.sbox.Info().Interfaces() {
|
|
| 252 |
- if err := iface.Remove(); err != nil {
|
|
| 253 |
- logrus.Debugf("Remove interface %s failed: %v", iface.SrcName(), err)
|
|
| 254 |
- } |
|
| 255 |
- } |
|
| 256 |
- |
|
| 257 |
- for _, s := range n.subnets {
|
|
| 258 |
- if s.vxlanName != "" {
|
|
| 259 |
- err := deleteInterface(s.vxlanName) |
|
| 260 |
- if err != nil {
|
|
| 261 |
- logrus.Warnf("could not cleanup sandbox properly: %v", err)
|
|
| 262 |
- } |
|
| 263 |
- } |
|
| 264 |
- } |
|
| 265 |
- |
|
| 266 |
- n.sbox.Destroy() |
|
| 267 |
- n.sbox = nil |
|
| 268 |
- } |
|
| 269 |
-} |
|
| 270 |
- |
|
| 271 |
-func networkOnceInit() {
|
|
| 272 |
- if os.Getenv("_OVERLAY_HOST_MODE") != "" {
|
|
| 273 |
- hostMode = true |
|
| 274 |
- return |
|
| 275 |
- } |
|
| 276 |
- |
|
| 277 |
- err := createVxlan("testvxlan1", 1, 0)
|
|
| 278 |
- if err != nil {
|
|
| 279 |
- logrus.Errorf("Failed to create testvxlan1 interface: %v", err)
|
|
| 280 |
- return |
|
| 281 |
- } |
|
| 282 |
- |
|
| 283 |
- defer deleteInterface("testvxlan1")
|
|
| 284 |
-} |
|
| 285 |
- |
|
| 286 |
-func (n *network) generateVxlanName(s *subnet) string {
|
|
| 287 |
- id := n.id |
|
| 288 |
- if len(n.id) > 12 {
|
|
| 289 |
- id = n.id[:12] |
|
| 290 |
- } |
|
| 291 |
- |
|
| 292 |
- return "vx_" + id + "_0" |
|
| 293 |
-} |
|
| 294 |
- |
|
| 295 |
-func (n *network) generateBridgeName(s *subnet) string {
|
|
| 296 |
- id := n.id |
|
| 297 |
- if len(n.id) > 5 {
|
|
| 298 |
- id = n.id[:5] |
|
| 299 |
- } |
|
| 300 |
- |
|
| 301 |
- return n.getBridgeNamePrefix(s) + "_" + id + "_0" |
|
| 302 |
-} |
|
| 303 |
- |
|
| 304 |
-func (n *network) getBridgeNamePrefix(s *subnet) string {
|
|
| 305 |
- return "ov_" + fmt.Sprintf("%06x", n.vxlanID(s))
|
|
| 306 |
-} |
|
| 307 |
- |
|
| 308 |
-func isOverlap(nw *net.IPNet) bool {
|
|
| 309 |
- var nameservers []string |
|
| 310 |
- |
|
| 311 |
- if rc, err := resolvconf.Get(); err == nil {
|
|
| 312 |
- nameservers = resolvconf.GetNameserversAsCIDR(rc.Content) |
|
| 313 |
- } |
|
| 314 |
- |
|
| 315 |
- if err := netutils.CheckNameserverOverlaps(nameservers, nw); err != nil {
|
|
| 316 |
- return true |
|
| 317 |
- } |
|
| 318 |
- |
|
| 319 |
- if err := netutils.CheckRouteOverlaps(nw); err != nil {
|
|
| 320 |
- return true |
|
| 321 |
- } |
|
| 322 |
- |
|
| 323 |
- return false |
|
| 324 |
-} |
|
| 325 |
- |
|
| 326 |
-func (n *network) restoreSubnetSandbox(s *subnet, brName, vxlanName string) error {
|
|
| 327 |
- sbox := n.sandbox() |
|
| 328 |
- |
|
| 329 |
- // restore overlay osl sandbox |
|
| 330 |
- Ifaces := make(map[string][]osl.IfaceOption) |
|
| 331 |
- brIfaceOption := make([]osl.IfaceOption, 2) |
|
| 332 |
- brIfaceOption = append(brIfaceOption, sbox.InterfaceOptions().Address(s.gwIP)) |
|
| 333 |
- brIfaceOption = append(brIfaceOption, sbox.InterfaceOptions().Bridge(true)) |
|
| 334 |
- Ifaces[brName+"+br"] = brIfaceOption |
|
| 335 |
- |
|
| 336 |
- err := sbox.Restore(Ifaces, nil, nil, nil) |
|
| 337 |
- if err != nil {
|
|
| 338 |
- return err |
|
| 339 |
- } |
|
| 340 |
- |
|
| 341 |
- Ifaces = make(map[string][]osl.IfaceOption) |
|
| 342 |
- vxlanIfaceOption := make([]osl.IfaceOption, 1) |
|
| 343 |
- vxlanIfaceOption = append(vxlanIfaceOption, sbox.InterfaceOptions().Master(brName)) |
|
| 344 |
- Ifaces[vxlanName+"+vxlan"] = vxlanIfaceOption |
|
| 345 |
- err = sbox.Restore(Ifaces, nil, nil, nil) |
|
| 346 |
- if err != nil {
|
|
| 347 |
- return err |
|
| 348 |
- } |
|
| 349 |
- return nil |
|
| 350 |
-} |
|
| 351 |
- |
|
| 352 |
-func (n *network) addInterface(srcName, dstPrefix, name string, isBridge bool) error {
|
|
| 353 |
- return nil |
|
| 354 |
-} |
|
| 355 |
- |
|
| 356 |
-func (n *network) setupSubnetSandbox(s *subnet, brName, vxlanName string) error {
|
|
| 357 |
- |
|
| 358 |
- if hostMode {
|
|
| 359 |
- // Try to delete stale bridge interface if it exists |
|
| 360 |
- if err := deleteInterface(brName); err != nil {
|
|
| 361 |
- deleteInterfaceBySubnet(n.getBridgeNamePrefix(s), s) |
|
| 362 |
- } |
|
| 363 |
- |
|
| 364 |
- if isOverlap(s.subnetIP) {
|
|
| 365 |
- return fmt.Errorf("overlay subnet %s has conflicts in the host while running in host mode", s.subnetIP.String())
|
|
| 366 |
- } |
|
| 367 |
- } |
|
| 368 |
- |
|
| 369 |
- if !hostMode {
|
|
| 370 |
- // Try to find this subnet's vni is being used in some |
|
| 371 |
- // other namespace by looking at vniTbl that we just |
|
| 372 |
- // populated in the once init. If a hit is found then |
|
| 373 |
- // it must a stale namespace from previous |
|
| 374 |
- // life. Destroy it completely and reclaim resourced. |
|
| 375 |
- networkMu.Lock() |
|
| 376 |
- path, ok := vniTbl[n.vxlanID(s)] |
|
| 377 |
- networkMu.Unlock() |
|
| 378 |
- |
|
| 379 |
- if ok {
|
|
| 380 |
- os.Remove(path) |
|
| 381 |
- |
|
| 382 |
- networkMu.Lock() |
|
| 383 |
- delete(vniTbl, n.vxlanID(s)) |
|
| 384 |
- networkMu.Unlock() |
|
| 385 |
- } |
|
| 386 |
- } |
|
| 387 |
- |
|
| 388 |
- err := createVxlan(vxlanName, n.vxlanID(s), n.maxMTU()) |
|
| 389 |
- if err != nil {
|
|
| 390 |
- return err |
|
| 391 |
- } |
|
| 392 |
- |
|
| 393 |
- return nil |
|
| 394 |
-} |
|
| 395 |
- |
|
| 396 |
-func (n *network) initSubnetSandbox(s *subnet, restore bool) error {
|
|
| 397 |
- brName := n.generateBridgeName(s) |
|
| 398 |
- vxlanName := n.generateVxlanName(s) |
|
| 399 |
- |
|
| 400 |
- if restore {
|
|
| 401 |
- n.restoreSubnetSandbox(s, brName, vxlanName) |
|
| 402 |
- } else {
|
|
| 403 |
- n.setupSubnetSandbox(s, brName, vxlanName) |
|
| 404 |
- } |
|
| 405 |
- |
|
| 406 |
- n.Lock() |
|
| 407 |
- s.vxlanName = vxlanName |
|
| 408 |
- s.brName = brName |
|
| 409 |
- n.Unlock() |
|
| 410 |
- |
|
| 411 |
- return nil |
|
| 412 |
-} |
|
| 413 |
- |
|
| 414 |
-func (n *network) cleanupStaleSandboxes() {
|
|
| 415 |
- filepath.Walk(filepath.Dir(osl.GenerateKey("walk")),
|
|
| 416 |
- func(path string, info os.FileInfo, err error) error {
|
|
| 417 |
- _, fname := filepath.Split(path) |
|
| 418 |
- |
|
| 419 |
- pList := strings.Split(fname, "-") |
|
| 420 |
- if len(pList) <= 1 {
|
|
| 421 |
- return nil |
|
| 422 |
- } |
|
| 423 |
- |
|
| 424 |
- pattern := pList[1] |
|
| 425 |
- if strings.Contains(n.id, pattern) {
|
|
| 426 |
- // Now that we have destroyed this |
|
| 427 |
- // sandbox, remove all references to |
|
| 428 |
- // it in vniTbl so that we don't |
|
| 429 |
- // inadvertently destroy the sandbox |
|
| 430 |
- // created in this life. |
|
| 431 |
- networkMu.Lock() |
|
| 432 |
- for vni, tblPath := range vniTbl {
|
|
| 433 |
- if tblPath == path {
|
|
| 434 |
- delete(vniTbl, vni) |
|
| 435 |
- } |
|
| 436 |
- } |
|
| 437 |
- networkMu.Unlock() |
|
| 438 |
- } |
|
| 439 |
- |
|
| 440 |
- return nil |
|
| 441 |
- }) |
|
| 442 |
-} |
|
| 443 |
- |
|
| 444 |
-func (n *network) initSandbox(restore bool) error {
|
|
| 445 |
- n.Lock() |
|
| 446 |
- n.initEpoch++ |
|
| 447 |
- n.Unlock() |
|
| 448 |
- |
|
| 449 |
- networkOnce.Do(networkOnceInit) |
|
| 450 |
- |
|
| 451 |
- if !restore {
|
|
| 452 |
- // If there are any stale sandboxes related to this network |
|
| 453 |
- // from previous daemon life clean it up here |
|
| 454 |
- n.cleanupStaleSandboxes() |
|
| 455 |
- } |
|
| 456 |
- |
|
| 457 |
- // In the restore case network sandbox already exist; but we don't know |
|
| 458 |
- // what epoch number it was created with. It has to be retrieved by |
|
| 459 |
- // searching the net namespaces. |
|
| 460 |
- var key string |
|
| 461 |
- if restore {
|
|
| 462 |
- key = osl.GenerateKey("-" + n.id)
|
|
| 463 |
- } else {
|
|
| 464 |
- key = osl.GenerateKey(fmt.Sprintf("%d-", n.initEpoch) + n.id)
|
|
| 465 |
- } |
|
| 466 |
- |
|
| 467 |
- sbox, err := osl.NewSandbox(key, !hostMode, restore) |
|
| 468 |
- if err != nil {
|
|
| 469 |
- return fmt.Errorf("could not get network sandbox (oper %t): %v", restore, err)
|
|
| 470 |
- } |
|
| 471 |
- |
|
| 472 |
- n.setSandbox(sbox) |
|
| 473 |
- |
|
| 474 |
- if !restore {
|
|
| 475 |
- n.driver.peerDbUpdateSandbox(n.id) |
|
| 476 |
- } |
|
| 477 |
- |
|
| 478 |
- return nil |
|
| 479 |
-} |
|
| 480 |
- |
|
| 481 |
-func (d *driver) addNetwork(n *network) {
|
|
| 482 |
- d.Lock() |
|
| 483 |
- d.networks[n.id] = n |
|
| 484 |
- d.Unlock() |
|
| 485 |
-} |
|
| 486 |
- |
|
| 487 |
-func (d *driver) deleteNetwork(nid string) {
|
|
| 488 |
- d.Lock() |
|
| 489 |
- delete(d.networks, nid) |
|
| 490 |
- d.Unlock() |
|
| 491 |
-} |
|
| 492 |
- |
|
| 493 |
-func (d *driver) network(nid string) *network {
|
|
| 494 |
- d.Lock() |
|
| 495 |
- networks := d.networks |
|
| 496 |
- d.Unlock() |
|
| 497 |
- |
|
| 498 |
- n, ok := networks[nid] |
|
| 499 |
- if !ok {
|
|
| 500 |
- n = d.getNetworkFromStore(nid) |
|
| 501 |
- if n != nil {
|
|
| 502 |
- n.driver = d |
|
| 503 |
- n.endpoints = endpointTable{}
|
|
| 504 |
- n.once = &sync.Once{}
|
|
| 505 |
- networks[nid] = n |
|
| 506 |
- } |
|
| 507 |
- } |
|
| 508 |
- |
|
| 509 |
- return n |
|
| 510 |
-} |
|
| 511 |
- |
|
| 512 |
-func (d *driver) getNetworkFromStore(nid string) *network {
|
|
| 513 |
- if d.store == nil {
|
|
| 514 |
- return nil |
|
| 515 |
- } |
|
| 516 |
- |
|
| 517 |
- n := &network{id: nid}
|
|
| 518 |
- if err := d.store.GetObject(datastore.Key(n.Key()...), n); err != nil {
|
|
| 519 |
- return nil |
|
| 520 |
- } |
|
| 521 |
- |
|
| 522 |
- return n |
|
| 523 |
-} |
|
| 524 |
- |
|
| 525 |
-func (n *network) sandbox() osl.Sandbox {
|
|
| 526 |
- n.Lock() |
|
| 527 |
- defer n.Unlock() |
|
| 528 |
- |
|
| 529 |
- return n.sbox |
|
| 530 |
-} |
|
| 531 |
- |
|
| 532 |
-func (n *network) setSandbox(sbox osl.Sandbox) {
|
|
| 533 |
- n.Lock() |
|
| 534 |
- n.sbox = sbox |
|
| 535 |
- n.Unlock() |
|
| 536 |
-} |
|
| 537 |
- |
|
| 538 |
-func (n *network) vxlanID(s *subnet) uint32 {
|
|
| 539 |
- n.Lock() |
|
| 540 |
- defer n.Unlock() |
|
| 541 |
- |
|
| 542 |
- return s.vni |
|
| 543 |
-} |
|
| 544 |
- |
|
| 545 |
-func (n *network) setVxlanID(s *subnet, vni uint32) {
|
|
| 546 |
- n.Lock() |
|
| 547 |
- s.vni = vni |
|
| 548 |
- n.Unlock() |
|
| 549 |
-} |
|
| 550 |
- |
|
| 551 |
-func (n *network) Key() []string {
|
|
| 552 |
- return []string{"overlay", "network", n.id}
|
|
| 553 |
-} |
|
| 554 |
- |
|
| 555 |
-func (n *network) KeyPrefix() []string {
|
|
| 556 |
- return []string{"overlay", "network"}
|
|
| 557 |
-} |
|
| 558 |
- |
|
| 559 |
-func (n *network) Value() []byte {
|
|
| 560 |
- m := map[string]interface{}{}
|
|
| 561 |
- |
|
| 562 |
- netJSON := []*subnetJSON{}
|
|
| 563 |
- |
|
| 564 |
- for _, s := range n.subnets {
|
|
| 565 |
- sj := &subnetJSON{
|
|
| 566 |
- SubnetIP: s.subnetIP.String(), |
|
| 567 |
- GwIP: s.gwIP.String(), |
|
| 568 |
- Vni: s.vni, |
|
| 569 |
- } |
|
| 570 |
- netJSON = append(netJSON, sj) |
|
| 571 |
- } |
|
| 572 |
- |
|
| 573 |
- m["secure"] = n.secure |
|
| 574 |
- m["subnets"] = netJSON |
|
| 575 |
- m["mtu"] = n.mtu |
|
| 576 |
- b, err := json.Marshal(m) |
|
| 577 |
- if err != nil {
|
|
| 578 |
- return []byte{}
|
|
| 579 |
- } |
|
| 580 |
- |
|
| 581 |
- return b |
|
| 582 |
-} |
|
| 583 |
- |
|
| 584 |
-func (n *network) Index() uint64 {
|
|
| 585 |
- return n.dbIndex |
|
| 586 |
-} |
|
| 587 |
- |
|
| 588 |
-func (n *network) SetIndex(index uint64) {
|
|
| 589 |
- n.dbIndex = index |
|
| 590 |
- n.dbExists = true |
|
| 591 |
-} |
|
| 592 |
- |
|
| 593 |
-func (n *network) Exists() bool {
|
|
| 594 |
- return n.dbExists |
|
| 595 |
-} |
|
| 596 |
- |
|
| 597 |
-func (n *network) Skip() bool {
|
|
| 598 |
- return false |
|
| 599 |
-} |
|
| 600 |
- |
|
| 601 |
-func (n *network) SetValue(value []byte) error {
|
|
| 602 |
- var ( |
|
| 603 |
- m map[string]interface{}
|
|
| 604 |
- newNet bool |
|
| 605 |
- isMap = true |
|
| 606 |
- netJSON = []*subnetJSON{}
|
|
| 607 |
- ) |
|
| 608 |
- |
|
| 609 |
- if err := json.Unmarshal(value, &m); err != nil {
|
|
| 610 |
- err := json.Unmarshal(value, &netJSON) |
|
| 611 |
- if err != nil {
|
|
| 612 |
- return err |
|
| 613 |
- } |
|
| 614 |
- isMap = false |
|
| 615 |
- } |
|
| 616 |
- |
|
| 617 |
- if len(n.subnets) == 0 {
|
|
| 618 |
- newNet = true |
|
| 619 |
- } |
|
| 620 |
- |
|
| 621 |
- if isMap {
|
|
| 622 |
- if val, ok := m["secure"]; ok {
|
|
| 623 |
- n.secure = val.(bool) |
|
| 624 |
- } |
|
| 625 |
- if val, ok := m["mtu"]; ok {
|
|
| 626 |
- n.mtu = int(val.(float64)) |
|
| 627 |
- } |
|
| 628 |
- bytes, err := json.Marshal(m["subnets"]) |
|
| 629 |
- if err != nil {
|
|
| 630 |
- return err |
|
| 631 |
- } |
|
| 632 |
- if err := json.Unmarshal(bytes, &netJSON); err != nil {
|
|
| 633 |
- return err |
|
| 634 |
- } |
|
| 635 |
- } |
|
| 636 |
- |
|
| 637 |
- for _, sj := range netJSON {
|
|
| 638 |
- subnetIPstr := sj.SubnetIP |
|
| 639 |
- gwIPstr := sj.GwIP |
|
| 640 |
- vni := sj.Vni |
|
| 641 |
- |
|
| 642 |
- subnetIP, _ := types.ParseCIDR(subnetIPstr) |
|
| 643 |
- gwIP, _ := types.ParseCIDR(gwIPstr) |
|
| 644 |
- |
|
| 645 |
- if newNet {
|
|
| 646 |
- s := &subnet{
|
|
| 647 |
- subnetIP: subnetIP, |
|
| 648 |
- gwIP: gwIP, |
|
| 649 |
- vni: vni, |
|
| 650 |
- once: &sync.Once{},
|
|
| 651 |
- } |
|
| 652 |
- n.subnets = append(n.subnets, s) |
|
| 653 |
- } else {
|
|
| 654 |
- sNet := n.getMatchingSubnet(subnetIP) |
|
| 655 |
- if sNet != nil {
|
|
| 656 |
- sNet.vni = vni |
|
| 657 |
- } |
|
| 658 |
- } |
|
| 659 |
- } |
|
| 660 |
- return nil |
|
| 661 |
-} |
|
| 662 |
- |
|
| 663 |
-func (n *network) DataScope() string {
|
|
| 664 |
- return datastore.GlobalScope |
|
| 665 |
-} |
|
| 666 |
- |
|
| 667 |
-func (n *network) writeToStore() error {
|
|
| 668 |
- if n.driver.store == nil {
|
|
| 669 |
- return nil |
|
| 670 |
- } |
|
| 671 |
- |
|
| 672 |
- return n.driver.store.PutObjectAtomic(n) |
|
| 673 |
-} |
|
| 674 |
- |
|
| 675 |
-func (n *network) releaseVxlanID() ([]uint32, error) {
|
|
| 676 |
- if len(n.subnets) == 0 {
|
|
| 677 |
- return nil, nil |
|
| 678 |
- } |
|
| 679 |
- |
|
| 680 |
- if n.driver.store != nil {
|
|
| 681 |
- if err := n.driver.store.DeleteObjectAtomic(n); err != nil {
|
|
| 682 |
- if err == datastore.ErrKeyModified || err == datastore.ErrKeyNotFound {
|
|
| 683 |
- // In both the above cases we can safely assume that the key has been removed by some other |
|
| 684 |
- // instance and so simply get out of here |
|
| 685 |
- return nil, nil |
|
| 686 |
- } |
|
| 687 |
- |
|
| 688 |
- return nil, fmt.Errorf("failed to delete network to vxlan id map: %v", err)
|
|
| 689 |
- } |
|
| 690 |
- } |
|
| 691 |
- var vnis []uint32 |
|
| 692 |
- for _, s := range n.subnets {
|
|
| 693 |
- if n.driver.vxlanIdm != nil {
|
|
| 694 |
- vni := n.vxlanID(s) |
|
| 695 |
- vnis = append(vnis, vni) |
|
| 696 |
- n.driver.vxlanIdm.Release(uint64(vni)) |
|
| 697 |
- } |
|
| 698 |
- |
|
| 699 |
- n.setVxlanID(s, 0) |
|
| 700 |
- } |
|
| 701 |
- |
|
| 702 |
- return vnis, nil |
|
| 703 |
-} |
|
| 704 |
- |
|
| 705 |
-func (n *network) obtainVxlanID(s *subnet) error {
|
|
| 706 |
- //return if the subnet already has a vxlan id assigned |
|
| 707 |
- if s.vni != 0 {
|
|
| 708 |
- return nil |
|
| 709 |
- } |
|
| 710 |
- |
|
| 711 |
- if n.driver.store == nil {
|
|
| 712 |
- return fmt.Errorf("no valid vxlan id and no datastore configured, cannot obtain vxlan id")
|
|
| 713 |
- } |
|
| 714 |
- |
|
| 715 |
- for {
|
|
| 716 |
- if err := n.driver.store.GetObject(datastore.Key(n.Key()...), n); err != nil {
|
|
| 717 |
- return fmt.Errorf("getting network %q from datastore failed %v", n.id, err)
|
|
| 718 |
- } |
|
| 719 |
- |
|
| 720 |
- if s.vni == 0 {
|
|
| 721 |
- vxlanID, err := n.driver.vxlanIdm.GetID(true) |
|
| 722 |
- if err != nil {
|
|
| 723 |
- return fmt.Errorf("failed to allocate vxlan id: %v", err)
|
|
| 724 |
- } |
|
| 725 |
- |
|
| 726 |
- n.setVxlanID(s, uint32(vxlanID)) |
|
| 727 |
- if err := n.writeToStore(); err != nil {
|
|
| 728 |
- n.driver.vxlanIdm.Release(uint64(n.vxlanID(s))) |
|
| 729 |
- n.setVxlanID(s, 0) |
|
| 730 |
- if err == datastore.ErrKeyModified {
|
|
| 731 |
- continue |
|
| 732 |
- } |
|
| 733 |
- return fmt.Errorf("network %q failed to update data store: %v", n.id, err)
|
|
| 734 |
- } |
|
| 735 |
- return nil |
|
| 736 |
- } |
|
| 737 |
- return nil |
|
| 738 |
- } |
|
| 739 |
-} |
|
| 740 |
- |
|
| 741 |
-// contains return true if the passed ip belongs to one the network's |
|
| 742 |
-// subnets |
|
| 743 |
-func (n *network) contains(ip net.IP) bool {
|
|
| 744 |
- for _, s := range n.subnets {
|
|
| 745 |
- if s.subnetIP.Contains(ip) {
|
|
| 746 |
- return true |
|
| 747 |
- } |
|
| 748 |
- } |
|
| 749 |
- |
|
| 750 |
- return false |
|
| 751 |
-} |
|
| 752 |
- |
|
| 753 |
-// getSubnetforIP returns the subnet to which the given IP belongs |
|
| 754 |
-func (n *network) getSubnetforIP(ip *net.IPNet) *subnet {
|
|
| 755 |
- for _, s := range n.subnets {
|
|
| 756 |
- // first check if the mask lengths are the same |
|
| 757 |
- i, _ := s.subnetIP.Mask.Size() |
|
| 758 |
- j, _ := ip.Mask.Size() |
|
| 759 |
- if i != j {
|
|
| 760 |
- continue |
|
| 761 |
- } |
|
| 762 |
- if s.subnetIP.Contains(ip.IP) {
|
|
| 763 |
- return s |
|
| 764 |
- } |
|
| 765 |
- } |
|
| 766 |
- return nil |
|
| 767 |
-} |
|
| 768 |
- |
|
| 769 |
-// getMatchingSubnet return the network's subnet that matches the input |
|
| 770 |
-func (n *network) getMatchingSubnet(ip *net.IPNet) *subnet {
|
|
| 771 |
- if ip == nil {
|
|
| 772 |
- return nil |
|
| 773 |
- } |
|
| 774 |
- for _, s := range n.subnets {
|
|
| 775 |
- // first check if the mask lengths are the same |
|
| 776 |
- i, _ := s.subnetIP.Mask.Size() |
|
| 777 |
- j, _ := ip.Mask.Size() |
|
| 778 |
- if i != j {
|
|
| 779 |
- continue |
|
| 780 |
- } |
|
| 781 |
- if s.subnetIP.IP.Equal(ip.IP) {
|
|
| 782 |
- return s |
|
| 783 |
- } |
|
| 784 |
- } |
|
| 785 |
- return nil |
|
| 786 |
-} |
| 787 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,233 +0,0 @@ |
| 1 |
-package overlay |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "net" |
|
| 6 |
- "strings" |
|
| 7 |
- "time" |
|
| 8 |
- |
|
| 9 |
- "github.com/hashicorp/serf/serf" |
|
| 10 |
- "github.com/sirupsen/logrus" |
|
| 11 |
-) |
|
| 12 |
- |
|
| 13 |
-type ovNotify struct {
|
|
| 14 |
- action string |
|
| 15 |
- ep *endpoint |
|
| 16 |
- nw *network |
|
| 17 |
-} |
|
| 18 |
- |
|
| 19 |
-type logWriter struct{}
|
|
| 20 |
- |
|
| 21 |
-func (l *logWriter) Write(p []byte) (int, error) {
|
|
| 22 |
- str := string(p) |
|
| 23 |
- |
|
| 24 |
- switch {
|
|
| 25 |
- case strings.Contains(str, "[WARN]"): |
|
| 26 |
- logrus.Warn(str) |
|
| 27 |
- case strings.Contains(str, "[DEBUG]"): |
|
| 28 |
- logrus.Debug(str) |
|
| 29 |
- case strings.Contains(str, "[INFO]"): |
|
| 30 |
- logrus.Info(str) |
|
| 31 |
- case strings.Contains(str, "[ERR]"): |
|
| 32 |
- logrus.Error(str) |
|
| 33 |
- } |
|
| 34 |
- |
|
| 35 |
- return len(p), nil |
|
| 36 |
-} |
|
| 37 |
- |
|
| 38 |
-func (d *driver) serfInit() error {
|
|
| 39 |
- var err error |
|
| 40 |
- |
|
| 41 |
- config := serf.DefaultConfig() |
|
| 42 |
- config.Init() |
|
| 43 |
- config.MemberlistConfig.BindAddr = d.advertiseAddress |
|
| 44 |
- |
|
| 45 |
- d.eventCh = make(chan serf.Event, 4) |
|
| 46 |
- config.EventCh = d.eventCh |
|
| 47 |
- config.UserCoalescePeriod = 1 * time.Second |
|
| 48 |
- config.UserQuiescentPeriod = 50 * time.Millisecond |
|
| 49 |
- |
|
| 50 |
- config.LogOutput = &logWriter{}
|
|
| 51 |
- config.MemberlistConfig.LogOutput = config.LogOutput |
|
| 52 |
- |
|
| 53 |
- s, err := serf.Create(config) |
|
| 54 |
- if err != nil {
|
|
| 55 |
- return fmt.Errorf("failed to create cluster node: %v", err)
|
|
| 56 |
- } |
|
| 57 |
- defer func() {
|
|
| 58 |
- if err != nil {
|
|
| 59 |
- s.Shutdown() |
|
| 60 |
- } |
|
| 61 |
- }() |
|
| 62 |
- |
|
| 63 |
- d.serfInstance = s |
|
| 64 |
- |
|
| 65 |
- d.notifyCh = make(chan ovNotify) |
|
| 66 |
- d.exitCh = make(chan chan struct{})
|
|
| 67 |
- |
|
| 68 |
- go d.startSerfLoop(d.eventCh, d.notifyCh, d.exitCh) |
|
| 69 |
- return nil |
|
| 70 |
-} |
|
| 71 |
- |
|
| 72 |
-func (d *driver) serfJoin(neighIP string) error {
|
|
| 73 |
- if neighIP == "" {
|
|
| 74 |
- return fmt.Errorf("no neighbor to join")
|
|
| 75 |
- } |
|
| 76 |
- if _, err := d.serfInstance.Join([]string{neighIP}, false); err != nil {
|
|
| 77 |
- return fmt.Errorf("Failed to join the cluster at neigh IP %s: %v",
|
|
| 78 |
- neighIP, err) |
|
| 79 |
- } |
|
| 80 |
- return nil |
|
| 81 |
-} |
|
| 82 |
- |
|
| 83 |
-func (d *driver) notifyEvent(event ovNotify) {
|
|
| 84 |
- ep := event.ep |
|
| 85 |
- |
|
| 86 |
- ePayload := fmt.Sprintf("%s %s %s %s", event.action, ep.addr.IP.String(),
|
|
| 87 |
- net.IP(ep.addr.Mask).String(), ep.mac.String()) |
|
| 88 |
- eName := fmt.Sprintf("jl %s %s %s", d.serfInstance.LocalMember().Addr.String(),
|
|
| 89 |
- event.nw.id, ep.id) |
|
| 90 |
- |
|
| 91 |
- if err := d.serfInstance.UserEvent(eName, []byte(ePayload), true); err != nil {
|
|
| 92 |
- logrus.Errorf("Sending user event failed: %v\n", err)
|
|
| 93 |
- } |
|
| 94 |
-} |
|
| 95 |
- |
|
| 96 |
-func (d *driver) processEvent(u serf.UserEvent) {
|
|
| 97 |
- logrus.Debugf("Received user event name:%s, payload:%s\n", u.Name,
|
|
| 98 |
- string(u.Payload)) |
|
| 99 |
- |
|
| 100 |
- var dummy, action, vtepStr, nid, eid, ipStr, maskStr, macStr string |
|
| 101 |
- if _, err := fmt.Sscan(u.Name, &dummy, &vtepStr, &nid, &eid); err != nil {
|
|
| 102 |
- fmt.Printf("Failed to scan name string: %v\n", err)
|
|
| 103 |
- } |
|
| 104 |
- |
|
| 105 |
- if _, err := fmt.Sscan(string(u.Payload), &action, |
|
| 106 |
- &ipStr, &maskStr, &macStr); err != nil {
|
|
| 107 |
- fmt.Printf("Failed to scan value string: %v\n", err)
|
|
| 108 |
- } |
|
| 109 |
- |
|
| 110 |
- logrus.Debugf("Parsed data = %s/%s/%s/%s/%s/%s\n", nid, eid, vtepStr, ipStr, maskStr, macStr)
|
|
| 111 |
- |
|
| 112 |
- mac, err := net.ParseMAC(macStr) |
|
| 113 |
- if err != nil {
|
|
| 114 |
- logrus.Errorf("Failed to parse mac: %v\n", err)
|
|
| 115 |
- } |
|
| 116 |
- |
|
| 117 |
- if d.serfInstance.LocalMember().Addr.String() == vtepStr {
|
|
| 118 |
- return |
|
| 119 |
- } |
|
| 120 |
- |
|
| 121 |
- switch action {
|
|
| 122 |
- case "join": |
|
| 123 |
- if err := d.peerAdd(nid, eid, net.ParseIP(ipStr), net.IPMask(net.ParseIP(maskStr).To4()), mac, |
|
| 124 |
- net.ParseIP(vtepStr), true); err != nil {
|
|
| 125 |
- logrus.Errorf("Peer add failed in the driver: %v\n", err)
|
|
| 126 |
- } |
|
| 127 |
- case "leave": |
|
| 128 |
- if err := d.peerDelete(nid, eid, net.ParseIP(ipStr), net.IPMask(net.ParseIP(maskStr).To4()), mac, |
|
| 129 |
- net.ParseIP(vtepStr), true); err != nil {
|
|
| 130 |
- logrus.Errorf("Peer delete failed in the driver: %v\n", err)
|
|
| 131 |
- } |
|
| 132 |
- } |
|
| 133 |
-} |
|
| 134 |
- |
|
| 135 |
-func (d *driver) processQuery(q *serf.Query) {
|
|
| 136 |
- logrus.Debugf("Received query name:%s, payload:%s\n", q.Name,
|
|
| 137 |
- string(q.Payload)) |
|
| 138 |
- |
|
| 139 |
- var nid, ipStr string |
|
| 140 |
- if _, err := fmt.Sscan(string(q.Payload), &nid, &ipStr); err != nil {
|
|
| 141 |
- fmt.Printf("Failed to scan query payload string: %v\n", err)
|
|
| 142 |
- } |
|
| 143 |
- |
|
| 144 |
- peerMac, peerIPMask, vtep, err := d.peerDbSearch(nid, net.ParseIP(ipStr)) |
|
| 145 |
- if err != nil {
|
|
| 146 |
- return |
|
| 147 |
- } |
|
| 148 |
- |
|
| 149 |
- q.Respond([]byte(fmt.Sprintf("%s %s %s", peerMac.String(), net.IP(peerIPMask).String(), vtep.String())))
|
|
| 150 |
-} |
|
| 151 |
- |
|
| 152 |
-func (d *driver) resolvePeer(nid string, peerIP net.IP) (net.HardwareAddr, net.IPMask, net.IP, error) {
|
|
| 153 |
- if d.serfInstance == nil {
|
|
| 154 |
- return nil, nil, nil, fmt.Errorf("could not resolve peer: serf instance not initialized")
|
|
| 155 |
- } |
|
| 156 |
- |
|
| 157 |
- qPayload := fmt.Sprintf("%s %s", string(nid), peerIP.String())
|
|
| 158 |
- resp, err := d.serfInstance.Query("peerlookup", []byte(qPayload), nil)
|
|
| 159 |
- if err != nil {
|
|
| 160 |
- return nil, nil, nil, fmt.Errorf("resolving peer by querying the cluster failed: %v", err)
|
|
| 161 |
- } |
|
| 162 |
- |
|
| 163 |
- respCh := resp.ResponseCh() |
|
| 164 |
- select {
|
|
| 165 |
- case r := <-respCh: |
|
| 166 |
- var macStr, maskStr, vtepStr string |
|
| 167 |
- if _, err := fmt.Sscan(string(r.Payload), &macStr, &maskStr, &vtepStr); err != nil {
|
|
| 168 |
- return nil, nil, nil, fmt.Errorf("bad response %q for the resolve query: %v", string(r.Payload), err)
|
|
| 169 |
- } |
|
| 170 |
- |
|
| 171 |
- mac, err := net.ParseMAC(macStr) |
|
| 172 |
- if err != nil {
|
|
| 173 |
- return nil, nil, nil, fmt.Errorf("failed to parse mac: %v", err)
|
|
| 174 |
- } |
|
| 175 |
- |
|
| 176 |
- return mac, net.IPMask(net.ParseIP(maskStr).To4()), net.ParseIP(vtepStr), nil |
|
| 177 |
- |
|
| 178 |
- case <-time.After(time.Second): |
|
| 179 |
- return nil, nil, nil, fmt.Errorf("timed out resolving peer by querying the cluster")
|
|
| 180 |
- } |
|
| 181 |
-} |
|
| 182 |
- |
|
| 183 |
-func (d *driver) startSerfLoop(eventCh chan serf.Event, notifyCh chan ovNotify, |
|
| 184 |
- exitCh chan chan struct{}) {
|
|
| 185 |
- |
|
| 186 |
- for {
|
|
| 187 |
- select {
|
|
| 188 |
- case notify, ok := <-notifyCh: |
|
| 189 |
- if !ok {
|
|
| 190 |
- break |
|
| 191 |
- } |
|
| 192 |
- |
|
| 193 |
- d.notifyEvent(notify) |
|
| 194 |
- case ch, ok := <-exitCh: |
|
| 195 |
- if !ok {
|
|
| 196 |
- break |
|
| 197 |
- } |
|
| 198 |
- |
|
| 199 |
- if err := d.serfInstance.Leave(); err != nil {
|
|
| 200 |
- logrus.Errorf("failed leaving the cluster: %v\n", err)
|
|
| 201 |
- } |
|
| 202 |
- |
|
| 203 |
- d.serfInstance.Shutdown() |
|
| 204 |
- close(ch) |
|
| 205 |
- return |
|
| 206 |
- case e, ok := <-eventCh: |
|
| 207 |
- if !ok {
|
|
| 208 |
- break |
|
| 209 |
- } |
|
| 210 |
- |
|
| 211 |
- if e.EventType() == serf.EventQuery {
|
|
| 212 |
- d.processQuery(e.(*serf.Query)) |
|
| 213 |
- break |
|
| 214 |
- } |
|
| 215 |
- |
|
| 216 |
- u, ok := e.(serf.UserEvent) |
|
| 217 |
- if !ok {
|
|
| 218 |
- break |
|
| 219 |
- } |
|
| 220 |
- d.processEvent(u) |
|
| 221 |
- } |
|
| 222 |
- } |
|
| 223 |
-} |
|
| 224 |
- |
|
| 225 |
-func (d *driver) isSerfAlive() bool {
|
|
| 226 |
- d.Lock() |
|
| 227 |
- serfInstance := d.serfInstance |
|
| 228 |
- d.Unlock() |
|
| 229 |
- if serfInstance == nil || serfInstance.State() != serf.SerfAlive {
|
|
| 230 |
- return false |
|
| 231 |
- } |
|
| 232 |
- return true |
|
| 233 |
-} |
| 234 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,61 +0,0 @@ |
| 1 |
-package overlay |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "os/exec" |
|
| 6 |
- "strings" |
|
| 7 |
- |
|
| 8 |
- "github.com/docker/libnetwork/osl" |
|
| 9 |
-) |
|
| 10 |
- |
|
| 11 |
-func validateID(nid, eid string) error {
|
|
| 12 |
- if nid == "" {
|
|
| 13 |
- return fmt.Errorf("invalid network id")
|
|
| 14 |
- } |
|
| 15 |
- |
|
| 16 |
- if eid == "" {
|
|
| 17 |
- return fmt.Errorf("invalid endpoint id")
|
|
| 18 |
- } |
|
| 19 |
- |
|
| 20 |
- return nil |
|
| 21 |
-} |
|
| 22 |
- |
|
| 23 |
-func createVxlan(name string, vni uint32, mtu int) error {
|
|
| 24 |
- defer osl.InitOSContext()() |
|
| 25 |
- |
|
| 26 |
- // Get default interface to plumb the vxlan on |
|
| 27 |
- routeCmd := "/usr/sbin/ipadm show-addr -p -o addrobj " + |
|
| 28 |
- "`/usr/sbin/route get default | /usr/bin/grep interface | " + |
|
| 29 |
- "/usr/bin/awk '{print $2}'`"
|
|
| 30 |
- out, err := exec.Command("/usr/bin/bash", "-c", routeCmd).Output()
|
|
| 31 |
- if err != nil {
|
|
| 32 |
- return fmt.Errorf("cannot get default route: %v", err)
|
|
| 33 |
- } |
|
| 34 |
- |
|
| 35 |
- defaultInterface := strings.SplitN(string(out), "/", 2) |
|
| 36 |
- propList := fmt.Sprintf("interface=%s,vni=%d", defaultInterface[0], vni)
|
|
| 37 |
- |
|
| 38 |
- out, err = exec.Command("/usr/sbin/dladm", "create-vxlan", "-t", "-p", propList,
|
|
| 39 |
- name).Output() |
|
| 40 |
- if err != nil {
|
|
| 41 |
- return fmt.Errorf("error creating vxlan interface: %v %s", err, out)
|
|
| 42 |
- } |
|
| 43 |
- |
|
| 44 |
- return nil |
|
| 45 |
-} |
|
| 46 |
- |
|
| 47 |
-func deleteInterfaceBySubnet(brPrefix string, s *subnet) error {
|
|
| 48 |
- return nil |
|
| 49 |
- |
|
| 50 |
-} |
|
| 51 |
- |
|
| 52 |
-func deleteInterface(name string) error {
|
|
| 53 |
- defer osl.InitOSContext()() |
|
| 54 |
- |
|
| 55 |
- out, err := exec.Command("/usr/sbin/dladm", "delete-vxlan", name).Output()
|
|
| 56 |
- if err != nil {
|
|
| 57 |
- return fmt.Errorf("error creating vxlan interface: %v %s", err, out)
|
|
| 58 |
- } |
|
| 59 |
- |
|
| 60 |
- return nil |
|
| 61 |
-} |
| 62 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,367 +0,0 @@ |
| 1 |
-package overlay |
|
| 2 |
- |
|
| 3 |
-//go:generate protoc -I.:../../Godeps/_workspace/src/github.com/gogo/protobuf --gogo_out=import_path=github.com/docker/libnetwork/drivers/overlay,Mgogoproto/gogo.proto=github.com/gogo/protobuf/gogoproto:. overlay.proto |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "fmt" |
|
| 7 |
- "net" |
|
| 8 |
- "sync" |
|
| 9 |
- |
|
| 10 |
- "github.com/docker/libnetwork/datastore" |
|
| 11 |
- "github.com/docker/libnetwork/discoverapi" |
|
| 12 |
- "github.com/docker/libnetwork/driverapi" |
|
| 13 |
- "github.com/docker/libnetwork/idm" |
|
| 14 |
- "github.com/docker/libnetwork/netlabel" |
|
| 15 |
- "github.com/docker/libnetwork/osl" |
|
| 16 |
- "github.com/docker/libnetwork/types" |
|
| 17 |
- "github.com/hashicorp/serf/serf" |
|
| 18 |
- "github.com/sirupsen/logrus" |
|
| 19 |
-) |
|
| 20 |
- |
|
| 21 |
-// XXX OVERLAY_SOLARIS |
|
| 22 |
-// Might need changes for names/constant values in solaris |
|
| 23 |
-const ( |
|
| 24 |
- networkType = "overlay" |
|
| 25 |
- vethPrefix = "veth" |
|
| 26 |
- vethLen = 7 |
|
| 27 |
- vxlanIDStart = 256 |
|
| 28 |
- vxlanIDEnd = (1 << 24) - 1 |
|
| 29 |
- vxlanPort = 4789 |
|
| 30 |
- vxlanEncap = 50 |
|
| 31 |
- secureOption = "encrypted" |
|
| 32 |
-) |
|
| 33 |
- |
|
| 34 |
-var initVxlanIdm = make(chan (bool), 1) |
|
| 35 |
- |
|
| 36 |
-type driver struct {
|
|
| 37 |
- eventCh chan serf.Event |
|
| 38 |
- notifyCh chan ovNotify |
|
| 39 |
- exitCh chan chan struct{}
|
|
| 40 |
- bindAddress string |
|
| 41 |
- advertiseAddress string |
|
| 42 |
- neighIP string |
|
| 43 |
- config map[string]interface{}
|
|
| 44 |
- peerDb peerNetworkMap |
|
| 45 |
- secMap *encrMap |
|
| 46 |
- serfInstance *serf.Serf |
|
| 47 |
- networks networkTable |
|
| 48 |
- store datastore.DataStore |
|
| 49 |
- localStore datastore.DataStore |
|
| 50 |
- vxlanIdm *idm.Idm |
|
| 51 |
- once sync.Once |
|
| 52 |
- joinOnce sync.Once |
|
| 53 |
- keys []*key |
|
| 54 |
- sync.Mutex |
|
| 55 |
-} |
|
| 56 |
- |
|
| 57 |
-// Init registers a new instance of overlay driver |
|
| 58 |
-func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
|
| 59 |
- c := driverapi.Capability{
|
|
| 60 |
- DataScope: datastore.GlobalScope, |
|
| 61 |
- ConnectivityScope: datastore.GlobalScope, |
|
| 62 |
- } |
|
| 63 |
- d := &driver{
|
|
| 64 |
- networks: networkTable{},
|
|
| 65 |
- peerDb: peerNetworkMap{
|
|
| 66 |
- mp: map[string]*peerMap{},
|
|
| 67 |
- }, |
|
| 68 |
- secMap: &encrMap{nodes: map[string][]*spi{}},
|
|
| 69 |
- config: config, |
|
| 70 |
- } |
|
| 71 |
- |
|
| 72 |
- if data, ok := config[netlabel.GlobalKVClient]; ok {
|
|
| 73 |
- var err error |
|
| 74 |
- dsc, ok := data.(discoverapi.DatastoreConfigData) |
|
| 75 |
- if !ok {
|
|
| 76 |
- return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
|
| 77 |
- } |
|
| 78 |
- d.store, err = datastore.NewDataStoreFromConfig(dsc) |
|
| 79 |
- if err != nil {
|
|
| 80 |
- return types.InternalErrorf("failed to initialize data store: %v", err)
|
|
| 81 |
- } |
|
| 82 |
- } |
|
| 83 |
- |
|
| 84 |
- if data, ok := config[netlabel.LocalKVClient]; ok {
|
|
| 85 |
- var err error |
|
| 86 |
- dsc, ok := data.(discoverapi.DatastoreConfigData) |
|
| 87 |
- if !ok {
|
|
| 88 |
- return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
|
| 89 |
- } |
|
| 90 |
- d.localStore, err = datastore.NewDataStoreFromConfig(dsc) |
|
| 91 |
- if err != nil {
|
|
| 92 |
- return types.InternalErrorf("failed to initialize local data store: %v", err)
|
|
| 93 |
- } |
|
| 94 |
- } |
|
| 95 |
- |
|
| 96 |
- d.restoreEndpoints() |
|
| 97 |
- |
|
| 98 |
- return dc.RegisterDriver(networkType, d, c) |
|
| 99 |
-} |
|
| 100 |
- |
|
| 101 |
-// Endpoints are stored in the local store. Restore them and reconstruct the overlay sandbox |
|
| 102 |
-func (d *driver) restoreEndpoints() error {
|
|
| 103 |
- if d.localStore == nil {
|
|
| 104 |
- logrus.Warnf("Cannot restore overlay endpoints because local datastore is missing")
|
|
| 105 |
- return nil |
|
| 106 |
- } |
|
| 107 |
- kvol, err := d.localStore.List(datastore.Key(overlayEndpointPrefix), &endpoint{})
|
|
| 108 |
- if err != nil && err != datastore.ErrKeyNotFound {
|
|
| 109 |
- return fmt.Errorf("failed to read overlay endpoint from store: %v", err)
|
|
| 110 |
- } |
|
| 111 |
- |
|
| 112 |
- if err == datastore.ErrKeyNotFound {
|
|
| 113 |
- return nil |
|
| 114 |
- } |
|
| 115 |
- for _, kvo := range kvol {
|
|
| 116 |
- ep := kvo.(*endpoint) |
|
| 117 |
- n := d.network(ep.nid) |
|
| 118 |
- if n == nil {
|
|
| 119 |
- logrus.Debugf("Network (%s) not found for restored endpoint (%s)", ep.nid[0:7], ep.id[0:7])
|
|
| 120 |
- logrus.Debugf("Deleting stale overlay endpoint (%s) from store", ep.id[0:7])
|
|
| 121 |
- if err := d.deleteEndpointFromStore(ep); err != nil {
|
|
| 122 |
- logrus.Debugf("Failed to delete stale overlay endpoint (%s) from store", ep.id[0:7])
|
|
| 123 |
- } |
|
| 124 |
- continue |
|
| 125 |
- } |
|
| 126 |
- n.addEndpoint(ep) |
|
| 127 |
- |
|
| 128 |
- s := n.getSubnetforIP(ep.addr) |
|
| 129 |
- if s == nil {
|
|
| 130 |
- return fmt.Errorf("could not find subnet for endpoint %s", ep.id)
|
|
| 131 |
- } |
|
| 132 |
- |
|
| 133 |
- if err := n.joinSandbox(true); err != nil {
|
|
| 134 |
- return fmt.Errorf("restore network sandbox failed: %v", err)
|
|
| 135 |
- } |
|
| 136 |
- |
|
| 137 |
- if err := n.joinSubnetSandbox(s, true); err != nil {
|
|
| 138 |
- return fmt.Errorf("restore subnet sandbox failed for %q: %v", s.subnetIP.String(), err)
|
|
| 139 |
- } |
|
| 140 |
- |
|
| 141 |
- Ifaces := make(map[string][]osl.IfaceOption) |
|
| 142 |
- vethIfaceOption := make([]osl.IfaceOption, 1) |
|
| 143 |
- vethIfaceOption = append(vethIfaceOption, n.sbox.InterfaceOptions().Master(s.brName)) |
|
| 144 |
- Ifaces["veth+veth"] = vethIfaceOption |
|
| 145 |
- |
|
| 146 |
- err := n.sbox.Restore(Ifaces, nil, nil, nil) |
|
| 147 |
- if err != nil {
|
|
| 148 |
- return fmt.Errorf("failed to restore overlay sandbox: %v", err)
|
|
| 149 |
- } |
|
| 150 |
- |
|
| 151 |
- n.incEndpointCount() |
|
| 152 |
- d.peerDbAdd(ep.nid, ep.id, ep.addr.IP, ep.addr.Mask, ep.mac, net.ParseIP(d.advertiseAddress), true) |
|
| 153 |
- } |
|
| 154 |
- return nil |
|
| 155 |
-} |
|
| 156 |
- |
|
| 157 |
-// Fini cleans up the driver resources |
|
| 158 |
-func Fini(drv driverapi.Driver) {
|
|
| 159 |
- d := drv.(*driver) |
|
| 160 |
- |
|
| 161 |
- if d.exitCh != nil {
|
|
| 162 |
- waitCh := make(chan struct{})
|
|
| 163 |
- |
|
| 164 |
- d.exitCh <- waitCh |
|
| 165 |
- |
|
| 166 |
- <-waitCh |
|
| 167 |
- } |
|
| 168 |
-} |
|
| 169 |
- |
|
| 170 |
-func (d *driver) configure() error {
|
|
| 171 |
- if d.store == nil {
|
|
| 172 |
- return nil |
|
| 173 |
- } |
|
| 174 |
- |
|
| 175 |
- if d.vxlanIdm == nil {
|
|
| 176 |
- return d.initializeVxlanIdm() |
|
| 177 |
- } |
|
| 178 |
- |
|
| 179 |
- return nil |
|
| 180 |
-} |
|
| 181 |
- |
|
| 182 |
-func (d *driver) initializeVxlanIdm() error {
|
|
| 183 |
- var err error |
|
| 184 |
- |
|
| 185 |
- initVxlanIdm <- true |
|
| 186 |
- defer func() { <-initVxlanIdm }()
|
|
| 187 |
- |
|
| 188 |
- if d.vxlanIdm != nil {
|
|
| 189 |
- return nil |
|
| 190 |
- } |
|
| 191 |
- |
|
| 192 |
- d.vxlanIdm, err = idm.New(d.store, "vxlan-id", vxlanIDStart, vxlanIDEnd) |
|
| 193 |
- if err != nil {
|
|
| 194 |
- return fmt.Errorf("failed to initialize vxlan id manager: %v", err)
|
|
| 195 |
- } |
|
| 196 |
- |
|
| 197 |
- return nil |
|
| 198 |
-} |
|
| 199 |
- |
|
| 200 |
-func (d *driver) Type() string {
|
|
| 201 |
- return networkType |
|
| 202 |
-} |
|
| 203 |
- |
|
| 204 |
-func (d *driver) IsBuiltIn() bool {
|
|
| 205 |
- return true |
|
| 206 |
-} |
|
| 207 |
- |
|
| 208 |
-func validateSelf(node string) error {
|
|
| 209 |
- advIP := net.ParseIP(node) |
|
| 210 |
- if advIP == nil {
|
|
| 211 |
- return fmt.Errorf("invalid self address (%s)", node)
|
|
| 212 |
- } |
|
| 213 |
- |
|
| 214 |
- addrs, err := net.InterfaceAddrs() |
|
| 215 |
- if err != nil {
|
|
| 216 |
- return fmt.Errorf("Unable to get interface addresses %v", err)
|
|
| 217 |
- } |
|
| 218 |
- for _, addr := range addrs {
|
|
| 219 |
- ip, _, err := net.ParseCIDR(addr.String()) |
|
| 220 |
- if err == nil && ip.Equal(advIP) {
|
|
| 221 |
- return nil |
|
| 222 |
- } |
|
| 223 |
- } |
|
| 224 |
- return fmt.Errorf("Multi-Host overlay networking requires cluster-advertise(%s) to be configured with a local ip-address that is reachable within the cluster", advIP.String())
|
|
| 225 |
-} |
|
| 226 |
- |
|
| 227 |
-func (d *driver) nodeJoin(advertiseAddress, bindAddress string, self bool) {
|
|
| 228 |
- if self && !d.isSerfAlive() {
|
|
| 229 |
- d.Lock() |
|
| 230 |
- d.advertiseAddress = advertiseAddress |
|
| 231 |
- d.bindAddress = bindAddress |
|
| 232 |
- d.Unlock() |
|
| 233 |
- |
|
| 234 |
- // If there is no cluster store there is no need to start serf. |
|
| 235 |
- if d.store != nil {
|
|
| 236 |
- if err := validateSelf(advertiseAddress); err != nil {
|
|
| 237 |
- logrus.Warn(err.Error()) |
|
| 238 |
- } |
|
| 239 |
- err := d.serfInit() |
|
| 240 |
- if err != nil {
|
|
| 241 |
- logrus.Errorf("initializing serf instance failed: %v", err)
|
|
| 242 |
- d.Lock() |
|
| 243 |
- d.advertiseAddress = "" |
|
| 244 |
- d.bindAddress = "" |
|
| 245 |
- d.Unlock() |
|
| 246 |
- return |
|
| 247 |
- } |
|
| 248 |
- } |
|
| 249 |
- } |
|
| 250 |
- |
|
| 251 |
- d.Lock() |
|
| 252 |
- if !self {
|
|
| 253 |
- d.neighIP = advertiseAddress |
|
| 254 |
- } |
|
| 255 |
- neighIP := d.neighIP |
|
| 256 |
- d.Unlock() |
|
| 257 |
- |
|
| 258 |
- if d.serfInstance != nil && neighIP != "" {
|
|
| 259 |
- var err error |
|
| 260 |
- d.joinOnce.Do(func() {
|
|
| 261 |
- err = d.serfJoin(neighIP) |
|
| 262 |
- if err == nil {
|
|
| 263 |
- d.pushLocalDb() |
|
| 264 |
- } |
|
| 265 |
- }) |
|
| 266 |
- if err != nil {
|
|
| 267 |
- logrus.Errorf("joining serf neighbor %s failed: %v", advertiseAddress, err)
|
|
| 268 |
- d.Lock() |
|
| 269 |
- d.joinOnce = sync.Once{}
|
|
| 270 |
- d.Unlock() |
|
| 271 |
- return |
|
| 272 |
- } |
|
| 273 |
- } |
|
| 274 |
-} |
|
| 275 |
- |
|
| 276 |
-func (d *driver) pushLocalEndpointEvent(action, nid, eid string) {
|
|
| 277 |
- n := d.network(nid) |
|
| 278 |
- if n == nil {
|
|
| 279 |
- logrus.Debugf("Error pushing local endpoint event for network %s", nid)
|
|
| 280 |
- return |
|
| 281 |
- } |
|
| 282 |
- ep := n.endpoint(eid) |
|
| 283 |
- if ep == nil {
|
|
| 284 |
- logrus.Debugf("Error pushing local endpoint event for ep %s / %s", nid, eid)
|
|
| 285 |
- return |
|
| 286 |
- } |
|
| 287 |
- |
|
| 288 |
- if !d.isSerfAlive() {
|
|
| 289 |
- return |
|
| 290 |
- } |
|
| 291 |
- d.notifyCh <- ovNotify{
|
|
| 292 |
- action: "join", |
|
| 293 |
- nw: n, |
|
| 294 |
- ep: ep, |
|
| 295 |
- } |
|
| 296 |
-} |
|
| 297 |
- |
|
| 298 |
-// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster |
|
| 299 |
-func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
|
| 300 |
- var err error |
|
| 301 |
- switch dType {
|
|
| 302 |
- case discoverapi.NodeDiscovery: |
|
| 303 |
- nodeData, ok := data.(discoverapi.NodeDiscoveryData) |
|
| 304 |
- if !ok || nodeData.Address == "" {
|
|
| 305 |
- return fmt.Errorf("invalid discovery data")
|
|
| 306 |
- } |
|
| 307 |
- d.nodeJoin(nodeData.Address, nodeData.BindAddress, nodeData.Self) |
|
| 308 |
- case discoverapi.DatastoreConfig: |
|
| 309 |
- if d.store != nil {
|
|
| 310 |
- return types.ForbiddenErrorf("cannot accept datastore configuration: Overlay driver has a datastore configured already")
|
|
| 311 |
- } |
|
| 312 |
- dsc, ok := data.(discoverapi.DatastoreConfigData) |
|
| 313 |
- if !ok {
|
|
| 314 |
- return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
|
| 315 |
- } |
|
| 316 |
- d.store, err = datastore.NewDataStoreFromConfig(dsc) |
|
| 317 |
- if err != nil {
|
|
| 318 |
- return types.InternalErrorf("failed to initialize data store: %v", err)
|
|
| 319 |
- } |
|
| 320 |
- case discoverapi.EncryptionKeysConfig: |
|
| 321 |
- encrData, ok := data.(discoverapi.DriverEncryptionConfig) |
|
| 322 |
- if !ok {
|
|
| 323 |
- return fmt.Errorf("invalid encryption key notification data")
|
|
| 324 |
- } |
|
| 325 |
- keys := make([]*key, 0, len(encrData.Keys)) |
|
| 326 |
- for i := 0; i < len(encrData.Keys); i++ {
|
|
| 327 |
- k := &key{
|
|
| 328 |
- value: encrData.Keys[i], |
|
| 329 |
- tag: uint32(encrData.Tags[i]), |
|
| 330 |
- } |
|
| 331 |
- keys = append(keys, k) |
|
| 332 |
- } |
|
| 333 |
- d.setKeys(keys) |
|
| 334 |
- case discoverapi.EncryptionKeysUpdate: |
|
| 335 |
- var newKey, delKey, priKey *key |
|
| 336 |
- encrData, ok := data.(discoverapi.DriverEncryptionUpdate) |
|
| 337 |
- if !ok {
|
|
| 338 |
- return fmt.Errorf("invalid encryption key notification data")
|
|
| 339 |
- } |
|
| 340 |
- if encrData.Key != nil {
|
|
| 341 |
- newKey = &key{
|
|
| 342 |
- value: encrData.Key, |
|
| 343 |
- tag: uint32(encrData.Tag), |
|
| 344 |
- } |
|
| 345 |
- } |
|
| 346 |
- if encrData.Primary != nil {
|
|
| 347 |
- priKey = &key{
|
|
| 348 |
- value: encrData.Primary, |
|
| 349 |
- tag: uint32(encrData.PrimaryTag), |
|
| 350 |
- } |
|
| 351 |
- } |
|
| 352 |
- if encrData.Prune != nil {
|
|
| 353 |
- delKey = &key{
|
|
| 354 |
- value: encrData.Prune, |
|
| 355 |
- tag: uint32(encrData.PruneTag), |
|
| 356 |
- } |
|
| 357 |
- } |
|
| 358 |
- d.updateKeys(newKey, priKey, delKey) |
|
| 359 |
- default: |
|
| 360 |
- } |
|
| 361 |
- return nil |
|
| 362 |
-} |
|
| 363 |
- |
|
| 364 |
-// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster |
|
| 365 |
-func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
|
| 366 |
- return nil |
|
| 367 |
-} |
| 368 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,468 +0,0 @@ |
| 1 |
-// Code generated by protoc-gen-gogo. |
|
| 2 |
-// source: overlay.proto |
|
| 3 |
-// DO NOT EDIT! |
|
| 4 |
- |
|
| 5 |
-/* |
|
| 6 |
- Package overlay is a generated protocol buffer package. |
|
| 7 |
- |
|
| 8 |
- It is generated from these files: |
|
| 9 |
- overlay.proto |
|
| 10 |
- |
|
| 11 |
- It has these top-level messages: |
|
| 12 |
- PeerRecord |
|
| 13 |
-*/ |
|
| 14 |
-package overlay |
|
| 15 |
- |
|
| 16 |
-import proto "github.com/gogo/protobuf/proto" |
|
| 17 |
-import fmt "fmt" |
|
| 18 |
-import math "math" |
|
| 19 |
-import _ "github.com/gogo/protobuf/gogoproto" |
|
| 20 |
- |
|
| 21 |
-import strings "strings" |
|
| 22 |
-import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto" |
|
| 23 |
-import sort "sort" |
|
| 24 |
-import strconv "strconv" |
|
| 25 |
-import reflect "reflect" |
|
| 26 |
- |
|
| 27 |
-import io "io" |
|
| 28 |
- |
|
| 29 |
-// Reference imports to suppress errors if they are not otherwise used. |
|
| 30 |
-var _ = proto.Marshal |
|
| 31 |
-var _ = fmt.Errorf |
|
| 32 |
-var _ = math.Inf |
|
| 33 |
- |
|
| 34 |
-// This is a compile-time assertion to ensure that this generated file |
|
| 35 |
-// is compatible with the proto package it is being compiled against. |
|
| 36 |
-const _ = proto.GoGoProtoPackageIsVersion1 |
|
| 37 |
- |
|
| 38 |
-// PeerRecord defines the information corresponding to a peer |
|
| 39 |
-// container in the overlay network. |
|
| 40 |
-type PeerRecord struct {
|
|
| 41 |
- // Endpoint IP is the IP of the container attachment on the |
|
| 42 |
- // given overlay network. |
|
| 43 |
- EndpointIP string `protobuf:"bytes,1,opt,name=endpoint_ip,json=endpointIp,proto3" json:"endpoint_ip,omitempty"` |
|
| 44 |
- // Endpoint MAC is the mac address of the container attachment |
|
| 45 |
- // on the given overlay network. |
|
| 46 |
- EndpointMAC string `protobuf:"bytes,2,opt,name=endpoint_mac,json=endpointMac,proto3" json:"endpoint_mac,omitempty"` |
|
| 47 |
- // Tunnel Endpoint IP defines the host IP for the host in |
|
| 48 |
- // which this container is running and can be reached by |
|
| 49 |
- // building a tunnel to that host IP. |
|
| 50 |
- TunnelEndpointIP string `protobuf:"bytes,3,opt,name=tunnel_endpoint_ip,json=tunnelEndpointIp,proto3" json:"tunnel_endpoint_ip,omitempty"` |
|
| 51 |
-} |
|
| 52 |
- |
|
| 53 |
-func (m *PeerRecord) Reset() { *m = PeerRecord{} }
|
|
| 54 |
-func (*PeerRecord) ProtoMessage() {}
|
|
| 55 |
-func (*PeerRecord) Descriptor() ([]byte, []int) { return fileDescriptorOverlay, []int{0} }
|
|
| 56 |
- |
|
| 57 |
-func init() {
|
|
| 58 |
- proto.RegisterType((*PeerRecord)(nil), "overlay.PeerRecord") |
|
| 59 |
-} |
|
| 60 |
-func (this *PeerRecord) GoString() string {
|
|
| 61 |
- if this == nil {
|
|
| 62 |
- return "nil" |
|
| 63 |
- } |
|
| 64 |
- s := make([]string, 0, 7) |
|
| 65 |
- s = append(s, "&overlay.PeerRecord{")
|
|
| 66 |
- s = append(s, "EndpointIP: "+fmt.Sprintf("%#v", this.EndpointIP)+",\n")
|
|
| 67 |
- s = append(s, "EndpointMAC: "+fmt.Sprintf("%#v", this.EndpointMAC)+",\n")
|
|
| 68 |
- s = append(s, "TunnelEndpointIP: "+fmt.Sprintf("%#v", this.TunnelEndpointIP)+",\n")
|
|
| 69 |
- s = append(s, "}") |
|
| 70 |
- return strings.Join(s, "") |
|
| 71 |
-} |
|
| 72 |
-func valueToGoStringOverlay(v interface{}, typ string) string {
|
|
| 73 |
- rv := reflect.ValueOf(v) |
|
| 74 |
- if rv.IsNil() {
|
|
| 75 |
- return "nil" |
|
| 76 |
- } |
|
| 77 |
- pv := reflect.Indirect(rv).Interface() |
|
| 78 |
- return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
|
|
| 79 |
-} |
|
| 80 |
-func extensionToGoStringOverlay(e map[int32]github_com_gogo_protobuf_proto.Extension) string {
|
|
| 81 |
- if e == nil {
|
|
| 82 |
- return "nil" |
|
| 83 |
- } |
|
| 84 |
- s := "map[int32]proto.Extension{"
|
|
| 85 |
- keys := make([]int, 0, len(e)) |
|
| 86 |
- for k := range e {
|
|
| 87 |
- keys = append(keys, int(k)) |
|
| 88 |
- } |
|
| 89 |
- sort.Ints(keys) |
|
| 90 |
- ss := []string{}
|
|
| 91 |
- for _, k := range keys {
|
|
| 92 |
- ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString()) |
|
| 93 |
- } |
|
| 94 |
- s += strings.Join(ss, ",") + "}" |
|
| 95 |
- return s |
|
| 96 |
-} |
|
| 97 |
-func (m *PeerRecord) Marshal() (data []byte, err error) {
|
|
| 98 |
- size := m.Size() |
|
| 99 |
- data = make([]byte, size) |
|
| 100 |
- n, err := m.MarshalTo(data) |
|
| 101 |
- if err != nil {
|
|
| 102 |
- return nil, err |
|
| 103 |
- } |
|
| 104 |
- return data[:n], nil |
|
| 105 |
-} |
|
| 106 |
- |
|
| 107 |
-func (m *PeerRecord) MarshalTo(data []byte) (int, error) {
|
|
| 108 |
- var i int |
|
| 109 |
- _ = i |
|
| 110 |
- var l int |
|
| 111 |
- _ = l |
|
| 112 |
- if len(m.EndpointIP) > 0 {
|
|
| 113 |
- data[i] = 0xa |
|
| 114 |
- i++ |
|
| 115 |
- i = encodeVarintOverlay(data, i, uint64(len(m.EndpointIP))) |
|
| 116 |
- i += copy(data[i:], m.EndpointIP) |
|
| 117 |
- } |
|
| 118 |
- if len(m.EndpointMAC) > 0 {
|
|
| 119 |
- data[i] = 0x12 |
|
| 120 |
- i++ |
|
| 121 |
- i = encodeVarintOverlay(data, i, uint64(len(m.EndpointMAC))) |
|
| 122 |
- i += copy(data[i:], m.EndpointMAC) |
|
| 123 |
- } |
|
| 124 |
- if len(m.TunnelEndpointIP) > 0 {
|
|
| 125 |
- data[i] = 0x1a |
|
| 126 |
- i++ |
|
| 127 |
- i = encodeVarintOverlay(data, i, uint64(len(m.TunnelEndpointIP))) |
|
| 128 |
- i += copy(data[i:], m.TunnelEndpointIP) |
|
| 129 |
- } |
|
| 130 |
- return i, nil |
|
| 131 |
-} |
|
| 132 |
- |
|
| 133 |
-func encodeFixed64Overlay(data []byte, offset int, v uint64) int {
|
|
| 134 |
- data[offset] = uint8(v) |
|
| 135 |
- data[offset+1] = uint8(v >> 8) |
|
| 136 |
- data[offset+2] = uint8(v >> 16) |
|
| 137 |
- data[offset+3] = uint8(v >> 24) |
|
| 138 |
- data[offset+4] = uint8(v >> 32) |
|
| 139 |
- data[offset+5] = uint8(v >> 40) |
|
| 140 |
- data[offset+6] = uint8(v >> 48) |
|
| 141 |
- data[offset+7] = uint8(v >> 56) |
|
| 142 |
- return offset + 8 |
|
| 143 |
-} |
|
| 144 |
-func encodeFixed32Overlay(data []byte, offset int, v uint32) int {
|
|
| 145 |
- data[offset] = uint8(v) |
|
| 146 |
- data[offset+1] = uint8(v >> 8) |
|
| 147 |
- data[offset+2] = uint8(v >> 16) |
|
| 148 |
- data[offset+3] = uint8(v >> 24) |
|
| 149 |
- return offset + 4 |
|
| 150 |
-} |
|
| 151 |
-func encodeVarintOverlay(data []byte, offset int, v uint64) int {
|
|
| 152 |
- for v >= 1<<7 {
|
|
| 153 |
- data[offset] = uint8(v&0x7f | 0x80) |
|
| 154 |
- v >>= 7 |
|
| 155 |
- offset++ |
|
| 156 |
- } |
|
| 157 |
- data[offset] = uint8(v) |
|
| 158 |
- return offset + 1 |
|
| 159 |
-} |
|
| 160 |
-func (m *PeerRecord) Size() (n int) {
|
|
| 161 |
- var l int |
|
| 162 |
- _ = l |
|
| 163 |
- l = len(m.EndpointIP) |
|
| 164 |
- if l > 0 {
|
|
| 165 |
- n += 1 + l + sovOverlay(uint64(l)) |
|
| 166 |
- } |
|
| 167 |
- l = len(m.EndpointMAC) |
|
| 168 |
- if l > 0 {
|
|
| 169 |
- n += 1 + l + sovOverlay(uint64(l)) |
|
| 170 |
- } |
|
| 171 |
- l = len(m.TunnelEndpointIP) |
|
| 172 |
- if l > 0 {
|
|
| 173 |
- n += 1 + l + sovOverlay(uint64(l)) |
|
| 174 |
- } |
|
| 175 |
- return n |
|
| 176 |
-} |
|
| 177 |
- |
|
| 178 |
-func sovOverlay(x uint64) (n int) {
|
|
| 179 |
- for {
|
|
| 180 |
- n++ |
|
| 181 |
- x >>= 7 |
|
| 182 |
- if x == 0 {
|
|
| 183 |
- break |
|
| 184 |
- } |
|
| 185 |
- } |
|
| 186 |
- return n |
|
| 187 |
-} |
|
| 188 |
-func sozOverlay(x uint64) (n int) {
|
|
| 189 |
- return sovOverlay(uint64((x << 1) ^ uint64((int64(x) >> 63)))) |
|
| 190 |
-} |
|
| 191 |
-func (this *PeerRecord) String() string {
|
|
| 192 |
- if this == nil {
|
|
| 193 |
- return "nil" |
|
| 194 |
- } |
|
| 195 |
- s := strings.Join([]string{`&PeerRecord{`,
|
|
| 196 |
- `EndpointIP:` + fmt.Sprintf("%v", this.EndpointIP) + `,`,
|
|
| 197 |
- `EndpointMAC:` + fmt.Sprintf("%v", this.EndpointMAC) + `,`,
|
|
| 198 |
- `TunnelEndpointIP:` + fmt.Sprintf("%v", this.TunnelEndpointIP) + `,`,
|
|
| 199 |
- `}`, |
|
| 200 |
- }, "") |
|
| 201 |
- return s |
|
| 202 |
-} |
|
| 203 |
-func valueToStringOverlay(v interface{}) string {
|
|
| 204 |
- rv := reflect.ValueOf(v) |
|
| 205 |
- if rv.IsNil() {
|
|
| 206 |
- return "nil" |
|
| 207 |
- } |
|
| 208 |
- pv := reflect.Indirect(rv).Interface() |
|
| 209 |
- return fmt.Sprintf("*%v", pv)
|
|
| 210 |
-} |
|
| 211 |
-func (m *PeerRecord) Unmarshal(data []byte) error {
|
|
| 212 |
- l := len(data) |
|
| 213 |
- iNdEx := 0 |
|
| 214 |
- for iNdEx < l {
|
|
| 215 |
- preIndex := iNdEx |
|
| 216 |
- var wire uint64 |
|
| 217 |
- for shift := uint(0); ; shift += 7 {
|
|
| 218 |
- if shift >= 64 {
|
|
| 219 |
- return ErrIntOverflowOverlay |
|
| 220 |
- } |
|
| 221 |
- if iNdEx >= l {
|
|
| 222 |
- return io.ErrUnexpectedEOF |
|
| 223 |
- } |
|
| 224 |
- b := data[iNdEx] |
|
| 225 |
- iNdEx++ |
|
| 226 |
- wire |= (uint64(b) & 0x7F) << shift |
|
| 227 |
- if b < 0x80 {
|
|
| 228 |
- break |
|
| 229 |
- } |
|
| 230 |
- } |
|
| 231 |
- fieldNum := int32(wire >> 3) |
|
| 232 |
- wireType := int(wire & 0x7) |
|
| 233 |
- if wireType == 4 {
|
|
| 234 |
- return fmt.Errorf("proto: PeerRecord: wiretype end group for non-group")
|
|
| 235 |
- } |
|
| 236 |
- if fieldNum <= 0 {
|
|
| 237 |
- return fmt.Errorf("proto: PeerRecord: illegal tag %d (wire type %d)", fieldNum, wire)
|
|
| 238 |
- } |
|
| 239 |
- switch fieldNum {
|
|
| 240 |
- case 1: |
|
| 241 |
- if wireType != 2 {
|
|
| 242 |
- return fmt.Errorf("proto: wrong wireType = %d for field EndpointIP", wireType)
|
|
| 243 |
- } |
|
| 244 |
- var stringLen uint64 |
|
| 245 |
- for shift := uint(0); ; shift += 7 {
|
|
| 246 |
- if shift >= 64 {
|
|
| 247 |
- return ErrIntOverflowOverlay |
|
| 248 |
- } |
|
| 249 |
- if iNdEx >= l {
|
|
| 250 |
- return io.ErrUnexpectedEOF |
|
| 251 |
- } |
|
| 252 |
- b := data[iNdEx] |
|
| 253 |
- iNdEx++ |
|
| 254 |
- stringLen |= (uint64(b) & 0x7F) << shift |
|
| 255 |
- if b < 0x80 {
|
|
| 256 |
- break |
|
| 257 |
- } |
|
| 258 |
- } |
|
| 259 |
- intStringLen := int(stringLen) |
|
| 260 |
- if intStringLen < 0 {
|
|
| 261 |
- return ErrInvalidLengthOverlay |
|
| 262 |
- } |
|
| 263 |
- postIndex := iNdEx + intStringLen |
|
| 264 |
- if postIndex > l {
|
|
| 265 |
- return io.ErrUnexpectedEOF |
|
| 266 |
- } |
|
| 267 |
- m.EndpointIP = string(data[iNdEx:postIndex]) |
|
| 268 |
- iNdEx = postIndex |
|
| 269 |
- case 2: |
|
| 270 |
- if wireType != 2 {
|
|
| 271 |
- return fmt.Errorf("proto: wrong wireType = %d for field EndpointMAC", wireType)
|
|
| 272 |
- } |
|
| 273 |
- var stringLen uint64 |
|
| 274 |
- for shift := uint(0); ; shift += 7 {
|
|
| 275 |
- if shift >= 64 {
|
|
| 276 |
- return ErrIntOverflowOverlay |
|
| 277 |
- } |
|
| 278 |
- if iNdEx >= l {
|
|
| 279 |
- return io.ErrUnexpectedEOF |
|
| 280 |
- } |
|
| 281 |
- b := data[iNdEx] |
|
| 282 |
- iNdEx++ |
|
| 283 |
- stringLen |= (uint64(b) & 0x7F) << shift |
|
| 284 |
- if b < 0x80 {
|
|
| 285 |
- break |
|
| 286 |
- } |
|
| 287 |
- } |
|
| 288 |
- intStringLen := int(stringLen) |
|
| 289 |
- if intStringLen < 0 {
|
|
| 290 |
- return ErrInvalidLengthOverlay |
|
| 291 |
- } |
|
| 292 |
- postIndex := iNdEx + intStringLen |
|
| 293 |
- if postIndex > l {
|
|
| 294 |
- return io.ErrUnexpectedEOF |
|
| 295 |
- } |
|
| 296 |
- m.EndpointMAC = string(data[iNdEx:postIndex]) |
|
| 297 |
- iNdEx = postIndex |
|
| 298 |
- case 3: |
|
| 299 |
- if wireType != 2 {
|
|
| 300 |
- return fmt.Errorf("proto: wrong wireType = %d for field TunnelEndpointIP", wireType)
|
|
| 301 |
- } |
|
| 302 |
- var stringLen uint64 |
|
| 303 |
- for shift := uint(0); ; shift += 7 {
|
|
| 304 |
- if shift >= 64 {
|
|
| 305 |
- return ErrIntOverflowOverlay |
|
| 306 |
- } |
|
| 307 |
- if iNdEx >= l {
|
|
| 308 |
- return io.ErrUnexpectedEOF |
|
| 309 |
- } |
|
| 310 |
- b := data[iNdEx] |
|
| 311 |
- iNdEx++ |
|
| 312 |
- stringLen |= (uint64(b) & 0x7F) << shift |
|
| 313 |
- if b < 0x80 {
|
|
| 314 |
- break |
|
| 315 |
- } |
|
| 316 |
- } |
|
| 317 |
- intStringLen := int(stringLen) |
|
| 318 |
- if intStringLen < 0 {
|
|
| 319 |
- return ErrInvalidLengthOverlay |
|
| 320 |
- } |
|
| 321 |
- postIndex := iNdEx + intStringLen |
|
| 322 |
- if postIndex > l {
|
|
| 323 |
- return io.ErrUnexpectedEOF |
|
| 324 |
- } |
|
| 325 |
- m.TunnelEndpointIP = string(data[iNdEx:postIndex]) |
|
| 326 |
- iNdEx = postIndex |
|
| 327 |
- default: |
|
| 328 |
- iNdEx = preIndex |
|
| 329 |
- skippy, err := skipOverlay(data[iNdEx:]) |
|
| 330 |
- if err != nil {
|
|
| 331 |
- return err |
|
| 332 |
- } |
|
| 333 |
- if skippy < 0 {
|
|
| 334 |
- return ErrInvalidLengthOverlay |
|
| 335 |
- } |
|
| 336 |
- if (iNdEx + skippy) > l {
|
|
| 337 |
- return io.ErrUnexpectedEOF |
|
| 338 |
- } |
|
| 339 |
- iNdEx += skippy |
|
| 340 |
- } |
|
| 341 |
- } |
|
| 342 |
- |
|
| 343 |
- if iNdEx > l {
|
|
| 344 |
- return io.ErrUnexpectedEOF |
|
| 345 |
- } |
|
| 346 |
- return nil |
|
| 347 |
-} |
|
| 348 |
-func skipOverlay(data []byte) (n int, err error) {
|
|
| 349 |
- l := len(data) |
|
| 350 |
- iNdEx := 0 |
|
| 351 |
- for iNdEx < l {
|
|
| 352 |
- var wire uint64 |
|
| 353 |
- for shift := uint(0); ; shift += 7 {
|
|
| 354 |
- if shift >= 64 {
|
|
| 355 |
- return 0, ErrIntOverflowOverlay |
|
| 356 |
- } |
|
| 357 |
- if iNdEx >= l {
|
|
| 358 |
- return 0, io.ErrUnexpectedEOF |
|
| 359 |
- } |
|
| 360 |
- b := data[iNdEx] |
|
| 361 |
- iNdEx++ |
|
| 362 |
- wire |= (uint64(b) & 0x7F) << shift |
|
| 363 |
- if b < 0x80 {
|
|
| 364 |
- break |
|
| 365 |
- } |
|
| 366 |
- } |
|
| 367 |
- wireType := int(wire & 0x7) |
|
| 368 |
- switch wireType {
|
|
| 369 |
- case 0: |
|
| 370 |
- for shift := uint(0); ; shift += 7 {
|
|
| 371 |
- if shift >= 64 {
|
|
| 372 |
- return 0, ErrIntOverflowOverlay |
|
| 373 |
- } |
|
| 374 |
- if iNdEx >= l {
|
|
| 375 |
- return 0, io.ErrUnexpectedEOF |
|
| 376 |
- } |
|
| 377 |
- iNdEx++ |
|
| 378 |
- if data[iNdEx-1] < 0x80 {
|
|
| 379 |
- break |
|
| 380 |
- } |
|
| 381 |
- } |
|
| 382 |
- return iNdEx, nil |
|
| 383 |
- case 1: |
|
| 384 |
- iNdEx += 8 |
|
| 385 |
- return iNdEx, nil |
|
| 386 |
- case 2: |
|
| 387 |
- var length int |
|
| 388 |
- for shift := uint(0); ; shift += 7 {
|
|
| 389 |
- if shift >= 64 {
|
|
| 390 |
- return 0, ErrIntOverflowOverlay |
|
| 391 |
- } |
|
| 392 |
- if iNdEx >= l {
|
|
| 393 |
- return 0, io.ErrUnexpectedEOF |
|
| 394 |
- } |
|
| 395 |
- b := data[iNdEx] |
|
| 396 |
- iNdEx++ |
|
| 397 |
- length |= (int(b) & 0x7F) << shift |
|
| 398 |
- if b < 0x80 {
|
|
| 399 |
- break |
|
| 400 |
- } |
|
| 401 |
- } |
|
| 402 |
- iNdEx += length |
|
| 403 |
- if length < 0 {
|
|
| 404 |
- return 0, ErrInvalidLengthOverlay |
|
| 405 |
- } |
|
| 406 |
- return iNdEx, nil |
|
| 407 |
- case 3: |
|
| 408 |
- for {
|
|
| 409 |
- var innerWire uint64 |
|
| 410 |
- var start int = iNdEx |
|
| 411 |
- for shift := uint(0); ; shift += 7 {
|
|
| 412 |
- if shift >= 64 {
|
|
| 413 |
- return 0, ErrIntOverflowOverlay |
|
| 414 |
- } |
|
| 415 |
- if iNdEx >= l {
|
|
| 416 |
- return 0, io.ErrUnexpectedEOF |
|
| 417 |
- } |
|
| 418 |
- b := data[iNdEx] |
|
| 419 |
- iNdEx++ |
|
| 420 |
- innerWire |= (uint64(b) & 0x7F) << shift |
|
| 421 |
- if b < 0x80 {
|
|
| 422 |
- break |
|
| 423 |
- } |
|
| 424 |
- } |
|
| 425 |
- innerWireType := int(innerWire & 0x7) |
|
| 426 |
- if innerWireType == 4 {
|
|
| 427 |
- break |
|
| 428 |
- } |
|
| 429 |
- next, err := skipOverlay(data[start:]) |
|
| 430 |
- if err != nil {
|
|
| 431 |
- return 0, err |
|
| 432 |
- } |
|
| 433 |
- iNdEx = start + next |
|
| 434 |
- } |
|
| 435 |
- return iNdEx, nil |
|
| 436 |
- case 4: |
|
| 437 |
- return iNdEx, nil |
|
| 438 |
- case 5: |
|
| 439 |
- iNdEx += 4 |
|
| 440 |
- return iNdEx, nil |
|
| 441 |
- default: |
|
| 442 |
- return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
|
| 443 |
- } |
|
| 444 |
- } |
|
| 445 |
- panic("unreachable")
|
|
| 446 |
-} |
|
| 447 |
- |
|
| 448 |
-var ( |
|
| 449 |
- ErrInvalidLengthOverlay = fmt.Errorf("proto: negative length found during unmarshaling")
|
|
| 450 |
- ErrIntOverflowOverlay = fmt.Errorf("proto: integer overflow")
|
|
| 451 |
-) |
|
| 452 |
- |
|
| 453 |
-var fileDescriptorOverlay = []byte{
|
|
| 454 |
- // 195 bytes of a gzipped FileDescriptorProto |
|
| 455 |
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0xcd, 0x2f, 0x4b, 0x2d, |
|
| 456 |
- 0xca, 0x49, 0xac, 0xd4, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x87, 0x72, 0xa5, 0x44, 0xd2, |
|
| 457 |
- 0xf3, 0xd3, 0xf3, 0xc1, 0x62, 0xfa, 0x20, 0x16, 0x44, 0x5a, 0x69, 0x2b, 0x23, 0x17, 0x57, 0x40, |
|
| 458 |
- 0x6a, 0x6a, 0x51, 0x50, 0x6a, 0x72, 0x7e, 0x51, 0x8a, 0x90, 0x3e, 0x17, 0x77, 0x6a, 0x5e, 0x4a, |
|
| 459 |
- 0x41, 0x7e, 0x66, 0x5e, 0x49, 0x7c, 0x66, 0x81, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0xa7, 0x13, 0xdf, |
|
| 460 |
- 0xa3, 0x7b, 0xf2, 0x5c, 0xae, 0x50, 0x61, 0xcf, 0x80, 0x20, 0x2e, 0x98, 0x12, 0xcf, 0x02, 0x21, |
|
| 461 |
- 0x23, 0x2e, 0x1e, 0xb8, 0x86, 0xdc, 0xc4, 0x64, 0x09, 0x26, 0xb0, 0x0e, 0x7e, 0xa0, 0x0e, 0x6e, |
|
| 462 |
- 0x98, 0x0e, 0x5f, 0x47, 0xe7, 0x20, 0xb8, 0xa9, 0xbe, 0x89, 0xc9, 0x42, 0x4e, 0x5c, 0x42, 0x25, |
|
| 463 |
- 0xa5, 0x79, 0x79, 0xa9, 0x39, 0xf1, 0xc8, 0x76, 0x31, 0x83, 0x75, 0x8a, 0x00, 0x75, 0x0a, 0x84, |
|
| 464 |
- 0x80, 0x65, 0x91, 0x6c, 0x14, 0x28, 0x41, 0x15, 0x29, 0x70, 0x92, 0xb8, 0xf1, 0x50, 0x8e, 0xe1, |
|
| 465 |
- 0xc3, 0x43, 0x39, 0xc6, 0x86, 0x47, 0x72, 0x8c, 0x27, 0x80, 0xf8, 0x02, 0x10, 0x3f, 0x00, 0xe2, |
|
| 466 |
- 0x24, 0x36, 0xb0, 0xc7, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbf, 0xd7, 0x7d, 0x7d, 0x08, |
|
| 467 |
- 0x01, 0x00, 0x00, |
|
| 468 |
-} |
| 469 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,27 +0,0 @@ |
| 1 |
-syntax = "proto3"; |
|
| 2 |
- |
|
| 3 |
-import "gogoproto/gogo.proto"; |
|
| 4 |
- |
|
| 5 |
-package overlay; |
|
| 6 |
- |
|
| 7 |
-option (gogoproto.marshaler_all) = true; |
|
| 8 |
-option (gogoproto.unmarshaler_all) = true; |
|
| 9 |
-option (gogoproto.stringer_all) = true; |
|
| 10 |
-option (gogoproto.gostring_all) = true; |
|
| 11 |
-option (gogoproto.sizer_all) = true; |
|
| 12 |
-option (gogoproto.goproto_stringer_all) = false; |
|
| 13 |
- |
|
| 14 |
-// PeerRecord defines the information corresponding to a peer |
|
| 15 |
-// container in the overlay network. |
|
| 16 |
-message PeerRecord {
|
|
| 17 |
- // Endpoint IP is the IP of the container attachment on the |
|
| 18 |
- // given overlay network. |
|
| 19 |
- string endpoint_ip = 1 [(gogoproto.customname) = "EndpointIP"]; |
|
| 20 |
- // Endpoint MAC is the mac address of the container attachment |
|
| 21 |
- // on the given overlay network. |
|
| 22 |
- string endpoint_mac = 2 [(gogoproto.customname) = "EndpointMAC"]; |
|
| 23 |
- // Tunnel Endpoint IP defines the host IP for the host in |
|
| 24 |
- // which this container is running and can be reached by |
|
| 25 |
- // building a tunnel to that host IP. |
|
| 26 |
- string tunnel_endpoint_ip = 3 [(gogoproto.customname) = "TunnelEndpointIP"]; |
|
| 27 |
-} |
|
| 28 | 1 |
\ No newline at end of file |
| 29 | 2 |
deleted file mode 100644 |
| ... | ... |
@@ -1,336 +0,0 @@ |
| 1 |
-package overlay |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "net" |
|
| 6 |
- "sync" |
|
| 7 |
- |
|
| 8 |
- "github.com/sirupsen/logrus" |
|
| 9 |
-) |
|
| 10 |
- |
|
| 11 |
-const ovPeerTable = "overlay_peer_table" |
|
| 12 |
- |
|
| 13 |
-type peerKey struct {
|
|
| 14 |
- peerIP net.IP |
|
| 15 |
- peerMac net.HardwareAddr |
|
| 16 |
-} |
|
| 17 |
- |
|
| 18 |
-type peerEntry struct {
|
|
| 19 |
- eid string |
|
| 20 |
- vtep net.IP |
|
| 21 |
- peerIPMask net.IPMask |
|
| 22 |
- inSandbox bool |
|
| 23 |
- isLocal bool |
|
| 24 |
-} |
|
| 25 |
- |
|
| 26 |
-type peerMap struct {
|
|
| 27 |
- mp map[string]peerEntry |
|
| 28 |
- sync.Mutex |
|
| 29 |
-} |
|
| 30 |
- |
|
| 31 |
-type peerNetworkMap struct {
|
|
| 32 |
- mp map[string]*peerMap |
|
| 33 |
- sync.Mutex |
|
| 34 |
-} |
|
| 35 |
- |
|
| 36 |
-func (pKey peerKey) String() string {
|
|
| 37 |
- return fmt.Sprintf("%s %s", pKey.peerIP, pKey.peerMac)
|
|
| 38 |
-} |
|
| 39 |
- |
|
| 40 |
-func (pKey *peerKey) Scan(state fmt.ScanState, verb rune) error {
|
|
| 41 |
- ipB, err := state.Token(true, nil) |
|
| 42 |
- if err != nil {
|
|
| 43 |
- return err |
|
| 44 |
- } |
|
| 45 |
- |
|
| 46 |
- pKey.peerIP = net.ParseIP(string(ipB)) |
|
| 47 |
- |
|
| 48 |
- macB, err := state.Token(true, nil) |
|
| 49 |
- if err != nil {
|
|
| 50 |
- return err |
|
| 51 |
- } |
|
| 52 |
- |
|
| 53 |
- pKey.peerMac, err = net.ParseMAC(string(macB)) |
|
| 54 |
- if err != nil {
|
|
| 55 |
- return err |
|
| 56 |
- } |
|
| 57 |
- |
|
| 58 |
- return nil |
|
| 59 |
-} |
|
| 60 |
- |
|
| 61 |
-var peerDbWg sync.WaitGroup |
|
| 62 |
- |
|
| 63 |
-func (d *driver) peerDbWalk(f func(string, *peerKey, *peerEntry) bool) error {
|
|
| 64 |
- d.peerDb.Lock() |
|
| 65 |
- nids := []string{}
|
|
| 66 |
- for nid := range d.peerDb.mp {
|
|
| 67 |
- nids = append(nids, nid) |
|
| 68 |
- } |
|
| 69 |
- d.peerDb.Unlock() |
|
| 70 |
- |
|
| 71 |
- for _, nid := range nids {
|
|
| 72 |
- d.peerDbNetworkWalk(nid, func(pKey *peerKey, pEntry *peerEntry) bool {
|
|
| 73 |
- return f(nid, pKey, pEntry) |
|
| 74 |
- }) |
|
| 75 |
- } |
|
| 76 |
- return nil |
|
| 77 |
-} |
|
| 78 |
- |
|
| 79 |
-func (d *driver) peerDbNetworkWalk(nid string, f func(*peerKey, *peerEntry) bool) error {
|
|
| 80 |
- d.peerDb.Lock() |
|
| 81 |
- pMap, ok := d.peerDb.mp[nid] |
|
| 82 |
- if !ok {
|
|
| 83 |
- d.peerDb.Unlock() |
|
| 84 |
- return nil |
|
| 85 |
- } |
|
| 86 |
- d.peerDb.Unlock() |
|
| 87 |
- |
|
| 88 |
- pMap.Lock() |
|
| 89 |
- for pKeyStr, pEntry := range pMap.mp {
|
|
| 90 |
- var pKey peerKey |
|
| 91 |
- if _, err := fmt.Sscan(pKeyStr, &pKey); err != nil {
|
|
| 92 |
- logrus.Warnf("Peer key scan on network %s failed: %v", nid, err)
|
|
| 93 |
- } |
|
| 94 |
- |
|
| 95 |
- if f(&pKey, &pEntry) {
|
|
| 96 |
- pMap.Unlock() |
|
| 97 |
- return nil |
|
| 98 |
- } |
|
| 99 |
- } |
|
| 100 |
- pMap.Unlock() |
|
| 101 |
- |
|
| 102 |
- return nil |
|
| 103 |
-} |
|
| 104 |
- |
|
| 105 |
-func (d *driver) peerDbSearch(nid string, peerIP net.IP) (net.HardwareAddr, net.IPMask, net.IP, error) {
|
|
| 106 |
- var ( |
|
| 107 |
- peerMac net.HardwareAddr |
|
| 108 |
- vtep net.IP |
|
| 109 |
- peerIPMask net.IPMask |
|
| 110 |
- found bool |
|
| 111 |
- ) |
|
| 112 |
- |
|
| 113 |
- err := d.peerDbNetworkWalk(nid, func(pKey *peerKey, pEntry *peerEntry) bool {
|
|
| 114 |
- if pKey.peerIP.Equal(peerIP) {
|
|
| 115 |
- peerMac = pKey.peerMac |
|
| 116 |
- peerIPMask = pEntry.peerIPMask |
|
| 117 |
- vtep = pEntry.vtep |
|
| 118 |
- found = true |
|
| 119 |
- return found |
|
| 120 |
- } |
|
| 121 |
- |
|
| 122 |
- return found |
|
| 123 |
- }) |
|
| 124 |
- |
|
| 125 |
- if err != nil {
|
|
| 126 |
- return nil, nil, nil, fmt.Errorf("peerdb search for peer ip %q failed: %v", peerIP, err)
|
|
| 127 |
- } |
|
| 128 |
- |
|
| 129 |
- if !found {
|
|
| 130 |
- return nil, nil, nil, fmt.Errorf("peer ip %q not found in peerdb", peerIP)
|
|
| 131 |
- } |
|
| 132 |
- |
|
| 133 |
- return peerMac, peerIPMask, vtep, nil |
|
| 134 |
-} |
|
| 135 |
- |
|
| 136 |
-func (d *driver) peerDbAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask, |
|
| 137 |
- peerMac net.HardwareAddr, vtep net.IP, isLocal bool) {
|
|
| 138 |
- |
|
| 139 |
- peerDbWg.Wait() |
|
| 140 |
- |
|
| 141 |
- d.peerDb.Lock() |
|
| 142 |
- pMap, ok := d.peerDb.mp[nid] |
|
| 143 |
- if !ok {
|
|
| 144 |
- d.peerDb.mp[nid] = &peerMap{
|
|
| 145 |
- mp: make(map[string]peerEntry), |
|
| 146 |
- } |
|
| 147 |
- |
|
| 148 |
- pMap = d.peerDb.mp[nid] |
|
| 149 |
- } |
|
| 150 |
- d.peerDb.Unlock() |
|
| 151 |
- |
|
| 152 |
- pKey := peerKey{
|
|
| 153 |
- peerIP: peerIP, |
|
| 154 |
- peerMac: peerMac, |
|
| 155 |
- } |
|
| 156 |
- |
|
| 157 |
- pEntry := peerEntry{
|
|
| 158 |
- eid: eid, |
|
| 159 |
- vtep: vtep, |
|
| 160 |
- peerIPMask: peerIPMask, |
|
| 161 |
- isLocal: isLocal, |
|
| 162 |
- } |
|
| 163 |
- |
|
| 164 |
- pMap.Lock() |
|
| 165 |
- pMap.mp[pKey.String()] = pEntry |
|
| 166 |
- pMap.Unlock() |
|
| 167 |
-} |
|
| 168 |
- |
|
| 169 |
-func (d *driver) peerDbDelete(nid, eid string, peerIP net.IP, peerIPMask net.IPMask, |
|
| 170 |
- peerMac net.HardwareAddr, vtep net.IP) {
|
|
| 171 |
- peerDbWg.Wait() |
|
| 172 |
- |
|
| 173 |
- d.peerDb.Lock() |
|
| 174 |
- pMap, ok := d.peerDb.mp[nid] |
|
| 175 |
- if !ok {
|
|
| 176 |
- d.peerDb.Unlock() |
|
| 177 |
- return |
|
| 178 |
- } |
|
| 179 |
- d.peerDb.Unlock() |
|
| 180 |
- |
|
| 181 |
- pKey := peerKey{
|
|
| 182 |
- peerIP: peerIP, |
|
| 183 |
- peerMac: peerMac, |
|
| 184 |
- } |
|
| 185 |
- |
|
| 186 |
- pMap.Lock() |
|
| 187 |
- delete(pMap.mp, pKey.String()) |
|
| 188 |
- pMap.Unlock() |
|
| 189 |
-} |
|
| 190 |
- |
|
| 191 |
-func (d *driver) peerDbUpdateSandbox(nid string) {
|
|
| 192 |
- d.peerDb.Lock() |
|
| 193 |
- pMap, ok := d.peerDb.mp[nid] |
|
| 194 |
- if !ok {
|
|
| 195 |
- d.peerDb.Unlock() |
|
| 196 |
- return |
|
| 197 |
- } |
|
| 198 |
- d.peerDb.Unlock() |
|
| 199 |
- |
|
| 200 |
- peerDbWg.Add(1) |
|
| 201 |
- |
|
| 202 |
- var peerOps []func() |
|
| 203 |
- pMap.Lock() |
|
| 204 |
- for pKeyStr, pEntry := range pMap.mp {
|
|
| 205 |
- var pKey peerKey |
|
| 206 |
- if _, err := fmt.Sscan(pKeyStr, &pKey); err != nil {
|
|
| 207 |
- fmt.Printf("peer key scan failed: %v", err)
|
|
| 208 |
- } |
|
| 209 |
- |
|
| 210 |
- if pEntry.isLocal {
|
|
| 211 |
- continue |
|
| 212 |
- } |
|
| 213 |
- |
|
| 214 |
- // Go captures variables by reference. The pEntry could be |
|
| 215 |
- // pointing to the same memory location for every iteration. Make |
|
| 216 |
- // a copy of pEntry before capturing it in the following closure. |
|
| 217 |
- entry := pEntry |
|
| 218 |
- op := func() {
|
|
| 219 |
- if err := d.peerAdd(nid, entry.eid, pKey.peerIP, entry.peerIPMask, |
|
| 220 |
- pKey.peerMac, entry.vtep, |
|
| 221 |
- false); err != nil {
|
|
| 222 |
- fmt.Printf("peerdbupdate in sandbox failed for ip %s and mac %s: %v",
|
|
| 223 |
- pKey.peerIP, pKey.peerMac, err) |
|
| 224 |
- } |
|
| 225 |
- } |
|
| 226 |
- |
|
| 227 |
- peerOps = append(peerOps, op) |
|
| 228 |
- } |
|
| 229 |
- pMap.Unlock() |
|
| 230 |
- |
|
| 231 |
- for _, op := range peerOps {
|
|
| 232 |
- op() |
|
| 233 |
- } |
|
| 234 |
- |
|
| 235 |
- peerDbWg.Done() |
|
| 236 |
-} |
|
| 237 |
- |
|
| 238 |
-func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask, |
|
| 239 |
- peerMac net.HardwareAddr, vtep net.IP, updateDb bool) error {
|
|
| 240 |
- |
|
| 241 |
- if err := validateID(nid, eid); err != nil {
|
|
| 242 |
- return err |
|
| 243 |
- } |
|
| 244 |
- |
|
| 245 |
- if updateDb {
|
|
| 246 |
- d.peerDbAdd(nid, eid, peerIP, peerIPMask, peerMac, vtep, false) |
|
| 247 |
- } |
|
| 248 |
- |
|
| 249 |
- n := d.network(nid) |
|
| 250 |
- if n == nil {
|
|
| 251 |
- return nil |
|
| 252 |
- } |
|
| 253 |
- |
|
| 254 |
- sbox := n.sandbox() |
|
| 255 |
- if sbox == nil {
|
|
| 256 |
- return nil |
|
| 257 |
- } |
|
| 258 |
- |
|
| 259 |
- IP := &net.IPNet{
|
|
| 260 |
- IP: peerIP, |
|
| 261 |
- Mask: peerIPMask, |
|
| 262 |
- } |
|
| 263 |
- |
|
| 264 |
- s := n.getSubnetforIP(IP) |
|
| 265 |
- if s == nil {
|
|
| 266 |
- return fmt.Errorf("couldn't find the subnet %q in network %q", IP.String(), n.id)
|
|
| 267 |
- } |
|
| 268 |
- |
|
| 269 |
- if err := n.obtainVxlanID(s); err != nil {
|
|
| 270 |
- return fmt.Errorf("couldn't get vxlan id for %q: %v", s.subnetIP.String(), err)
|
|
| 271 |
- } |
|
| 272 |
- |
|
| 273 |
- if err := n.joinSubnetSandbox(s, false); err != nil {
|
|
| 274 |
- return fmt.Errorf("subnet sandbox join failed for %q: %v", s.subnetIP.String(), err)
|
|
| 275 |
- } |
|
| 276 |
- |
|
| 277 |
- if err := d.checkEncryption(nid, vtep, n.vxlanID(s), false, true); err != nil {
|
|
| 278 |
- logrus.Warn(err) |
|
| 279 |
- } |
|
| 280 |
- |
|
| 281 |
- // Add neighbor entry for the peer IP |
|
| 282 |
- if err := sbox.AddNeighbor(peerIP, peerMac, false, sbox.NeighborOptions().LinkName(s.vxlanName)); err != nil {
|
|
| 283 |
- return fmt.Errorf("could not add neigbor entry into the sandbox: %v", err)
|
|
| 284 |
- } |
|
| 285 |
- |
|
| 286 |
- // XXX Add fdb entry to the bridge for the peer mac |
|
| 287 |
- |
|
| 288 |
- return nil |
|
| 289 |
-} |
|
| 290 |
- |
|
| 291 |
-func (d *driver) peerDelete(nid, eid string, peerIP net.IP, peerIPMask net.IPMask, |
|
| 292 |
- peerMac net.HardwareAddr, vtep net.IP, updateDb bool) error {
|
|
| 293 |
- |
|
| 294 |
- if err := validateID(nid, eid); err != nil {
|
|
| 295 |
- return err |
|
| 296 |
- } |
|
| 297 |
- |
|
| 298 |
- if updateDb {
|
|
| 299 |
- d.peerDbDelete(nid, eid, peerIP, peerIPMask, peerMac, vtep) |
|
| 300 |
- } |
|
| 301 |
- |
|
| 302 |
- n := d.network(nid) |
|
| 303 |
- if n == nil {
|
|
| 304 |
- return nil |
|
| 305 |
- } |
|
| 306 |
- |
|
| 307 |
- sbox := n.sandbox() |
|
| 308 |
- if sbox == nil {
|
|
| 309 |
- return nil |
|
| 310 |
- } |
|
| 311 |
- |
|
| 312 |
- // Delete fdb entry to the bridge for the peer mac |
|
| 313 |
- if err := sbox.DeleteNeighbor(vtep, peerMac, true); err != nil {
|
|
| 314 |
- return fmt.Errorf("could not delete fdb entry into the sandbox: %v", err)
|
|
| 315 |
- } |
|
| 316 |
- |
|
| 317 |
- // Delete neighbor entry for the peer IP |
|
| 318 |
- if err := sbox.DeleteNeighbor(peerIP, peerMac, true); err != nil {
|
|
| 319 |
- return fmt.Errorf("could not delete neigbor entry into the sandbox: %v", err)
|
|
| 320 |
- } |
|
| 321 |
- |
|
| 322 |
- if err := d.checkEncryption(nid, vtep, 0, false, false); err != nil {
|
|
| 323 |
- logrus.Warn(err) |
|
| 324 |
- } |
|
| 325 |
- |
|
| 326 |
- return nil |
|
| 327 |
-} |
|
| 328 |
- |
|
| 329 |
-func (d *driver) pushLocalDb() {
|
|
| 330 |
- d.peerDbWalk(func(nid string, pKey *peerKey, pEntry *peerEntry) bool {
|
|
| 331 |
- if pEntry.isLocal {
|
|
| 332 |
- d.pushLocalEndpointEvent("join", nid, pEntry.eid)
|
|
| 333 |
- } |
|
| 334 |
- return false |
|
| 335 |
- }) |
|
| 336 |
-} |
| 337 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,15 +0,0 @@ |
| 1 |
-package libnetwork |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "github.com/docker/libnetwork/drivers/null" |
|
| 5 |
- "github.com/docker/libnetwork/drivers/solaris/bridge" |
|
| 6 |
- "github.com/docker/libnetwork/drivers/solaris/overlay" |
|
| 7 |
-) |
|
| 8 |
- |
|
| 9 |
-func getInitializers(experimental bool) []initializer {
|
|
| 10 |
- return []initializer{
|
|
| 11 |
- {overlay.Init, "overlay"},
|
|
| 12 |
- {bridge.Init, "bridge"},
|
|
| 13 |
- {null.Init, "null"},
|
|
| 14 |
- } |
|
| 15 |
-} |
| ... | ... |
@@ -138,6 +138,15 @@ func (ec *endpointCnt) setCnt(cnt uint64) error {
|
| 138 | 138 |
} |
| 139 | 139 |
|
| 140 | 140 |
func (ec *endpointCnt) atomicIncDecEpCnt(inc bool) error {
|
| 141 |
+ store := ec.n.getController().getStore(ec.DataScope()) |
|
| 142 |
+ if store == nil {
|
|
| 143 |
+ return fmt.Errorf("store not found for scope %s", ec.DataScope())
|
|
| 144 |
+ } |
|
| 145 |
+ |
|
| 146 |
+ tmp := &endpointCnt{n: ec.n}
|
|
| 147 |
+ if err := store.GetObject(datastore.Key(ec.Key()...), tmp); err != nil {
|
|
| 148 |
+ return err |
|
| 149 |
+ } |
|
| 141 | 150 |
retry: |
| 142 | 151 |
ec.Lock() |
| 143 | 152 |
if inc {
|
| ... | ... |
@@ -149,11 +158,6 @@ retry: |
| 149 | 149 |
} |
| 150 | 150 |
ec.Unlock() |
| 151 | 151 |
|
| 152 |
- store := ec.n.getController().getStore(ec.DataScope()) |
|
| 153 |
- if store == nil {
|
|
| 154 |
- return fmt.Errorf("store not found for scope %s", ec.DataScope())
|
|
| 155 |
- } |
|
| 156 |
- |
|
| 157 | 152 |
if err := ec.n.getController().updateToStore(ec); err != nil {
|
| 158 | 153 |
if err == datastore.ErrKeyModified {
|
| 159 | 154 |
if err := store.GetObject(datastore.Key(ec.Key()...), ec); err != nil {
|
| 5 | 5 |
deleted file mode 100644 |
| ... | ... |
@@ -1,104 +0,0 @@ |
| 1 |
-// +build solaris |
|
| 2 |
- |
|
| 3 |
-package netutils |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "fmt" |
|
| 7 |
- "net" |
|
| 8 |
- "os/exec" |
|
| 9 |
- "strings" |
|
| 10 |
- |
|
| 11 |
- "github.com/docker/libnetwork/ipamutils" |
|
| 12 |
- "github.com/vishvananda/netlink" |
|
| 13 |
-) |
|
| 14 |
- |
|
| 15 |
-var ( |
|
| 16 |
- networkGetRoutesFct func(netlink.Link, int) ([]netlink.Route, error) |
|
| 17 |
-) |
|
| 18 |
- |
|
| 19 |
-// CheckRouteOverlaps checks whether the passed network overlaps with any existing routes |
|
| 20 |
-func CheckRouteOverlaps(toCheck *net.IPNet) error {
|
|
| 21 |
- return nil |
|
| 22 |
-} |
|
| 23 |
- |
|
| 24 |
-// ElectInterfaceAddresses looks for an interface on the OS with the specified name |
|
| 25 |
-// and returns returns all its IPv4 and IPv6 addresses in CIDR notation. |
|
| 26 |
-// If a failure in retrieving the addresses or no IPv4 address is found, an error is returned. |
|
| 27 |
-// If the interface does not exist, it chooses from a predefined |
|
| 28 |
-// list the first IPv4 address which does not conflict with other |
|
| 29 |
-// interfaces on the system. |
|
| 30 |
-func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) {
|
|
| 31 |
- var ( |
|
| 32 |
- v4Net *net.IPNet |
|
| 33 |
- ) |
|
| 34 |
- |
|
| 35 |
- out, err := exec.Command("/usr/sbin/ipadm", "show-addr",
|
|
| 36 |
- "-p", "-o", "addrobj,addr").Output() |
|
| 37 |
- if err != nil {
|
|
| 38 |
- fmt.Println("failed to list interfaces on system")
|
|
| 39 |
- return nil, nil, err |
|
| 40 |
- } |
|
| 41 |
- alist := strings.Fields(string(out)) |
|
| 42 |
- for _, a := range alist {
|
|
| 43 |
- linkandaddr := strings.SplitN(a, ":", 2) |
|
| 44 |
- if len(linkandaddr) != 2 {
|
|
| 45 |
- fmt.Println("failed to check interfaces on system: ", a)
|
|
| 46 |
- continue |
|
| 47 |
- } |
|
| 48 |
- gw := fmt.Sprintf("%s_gw0", name)
|
|
| 49 |
- link := strings.Split(linkandaddr[0], "/")[0] |
|
| 50 |
- addr := linkandaddr[1] |
|
| 51 |
- if gw != link {
|
|
| 52 |
- continue |
|
| 53 |
- } |
|
| 54 |
- _, ipnet, err := net.ParseCIDR(addr) |
|
| 55 |
- if err != nil {
|
|
| 56 |
- fmt.Println("failed to parse address: ", addr)
|
|
| 57 |
- continue |
|
| 58 |
- } |
|
| 59 |
- v4Net = ipnet |
|
| 60 |
- break |
|
| 61 |
- } |
|
| 62 |
- if v4Net == nil {
|
|
| 63 |
- v4Net, err = FindAvailableNetwork(ipamutils.PredefinedBroadNetworks) |
|
| 64 |
- if err != nil {
|
|
| 65 |
- return nil, nil, err |
|
| 66 |
- } |
|
| 67 |
- } |
|
| 68 |
- return []*net.IPNet{v4Net}, nil, nil
|
|
| 69 |
-} |
|
| 70 |
- |
|
| 71 |
-// FindAvailableNetwork returns a network from the passed list which does not |
|
| 72 |
-// overlap with existing interfaces in the system |
|
| 73 |
-func FindAvailableNetwork(list []*net.IPNet) (*net.IPNet, error) {
|
|
| 74 |
- out, err := exec.Command("/usr/sbin/ipadm", "show-addr",
|
|
| 75 |
- "-p", "-o", "addr").Output() |
|
| 76 |
- |
|
| 77 |
- if err != nil {
|
|
| 78 |
- fmt.Println("failed to list interfaces on system")
|
|
| 79 |
- return nil, err |
|
| 80 |
- } |
|
| 81 |
- ipaddrs := strings.Fields(string(out)) |
|
| 82 |
- inuse := []*net.IPNet{}
|
|
| 83 |
- for _, ip := range ipaddrs {
|
|
| 84 |
- _, ipnet, err := net.ParseCIDR(ip) |
|
| 85 |
- if err != nil {
|
|
| 86 |
- fmt.Println("failed to check interfaces on system: ", ip)
|
|
| 87 |
- continue |
|
| 88 |
- } |
|
| 89 |
- inuse = append(inuse, ipnet) |
|
| 90 |
- } |
|
| 91 |
- for _, avail := range list {
|
|
| 92 |
- is_avail := true |
|
| 93 |
- for _, ipnet := range inuse {
|
|
| 94 |
- if NetworkOverlaps(avail, ipnet) {
|
|
| 95 |
- is_avail = false |
|
| 96 |
- break |
|
| 97 |
- } |
|
| 98 |
- } |
|
| 99 |
- if is_avail {
|
|
| 100 |
- return avail, nil |
|
| 101 |
- } |
|
| 102 |
- } |
|
| 103 |
- return nil, fmt.Errorf("no available network")
|
|
| 104 |
-} |
| ... | ... |
@@ -17,15 +17,10 @@ import ( |
| 17 | 17 |
) |
| 18 | 18 |
|
| 19 | 19 |
const ( |
| 20 |
- // The garbage collection logic for entries leverage the presence of the network. |
|
| 21 |
- // For this reason the expiration time of the network is put slightly higher than the entry expiration so that |
|
| 22 |
- // there is at least 5 extra cycle to make sure that all the entries are properly deleted before deleting the network. |
|
| 23 |
- reapEntryInterval = 30 * time.Minute |
|
| 24 |
- reapNetworkInterval = reapEntryInterval + 5*reapPeriod |
|
| 25 |
- reapPeriod = 5 * time.Second |
|
| 26 |
- retryInterval = 1 * time.Second |
|
| 27 |
- nodeReapInterval = 24 * time.Hour |
|
| 28 |
- nodeReapPeriod = 2 * time.Hour |
|
| 20 |
+ reapPeriod = 5 * time.Second |
|
| 21 |
+ retryInterval = 1 * time.Second |
|
| 22 |
+ nodeReapInterval = 24 * time.Hour |
|
| 23 |
+ nodeReapPeriod = 2 * time.Hour |
|
| 29 | 24 |
) |
| 30 | 25 |
|
| 31 | 26 |
type logWriter struct{}
|
| ... | ... |
@@ -260,13 +255,18 @@ func (nDB *NetworkDB) triggerFunc(stagger time.Duration, C <-chan time.Time, sto |
| 260 | 260 |
func (nDB *NetworkDB) reapDeadNode() {
|
| 261 | 261 |
nDB.Lock() |
| 262 | 262 |
defer nDB.Unlock() |
| 263 |
- for id, n := range nDB.failedNodes {
|
|
| 264 |
- if n.reapTime > 0 {
|
|
| 265 |
- n.reapTime -= nodeReapPeriod |
|
| 266 |
- continue |
|
| 263 |
+ for _, nodeMap := range []map[string]*node{
|
|
| 264 |
+ nDB.failedNodes, |
|
| 265 |
+ nDB.leftNodes, |
|
| 266 |
+ } {
|
|
| 267 |
+ for id, n := range nodeMap {
|
|
| 268 |
+ if n.reapTime > nodeReapPeriod {
|
|
| 269 |
+ n.reapTime -= nodeReapPeriod |
|
| 270 |
+ continue |
|
| 271 |
+ } |
|
| 272 |
+ logrus.Debugf("Garbage collect node %v", n.Name)
|
|
| 273 |
+ delete(nodeMap, id) |
|
| 267 | 274 |
} |
| 268 |
- logrus.Debugf("Removing failed node %v from gossip cluster", n.Name)
|
|
| 269 |
- delete(nDB.failedNodes, id) |
|
| 270 | 275 |
} |
| 271 | 276 |
} |
| 272 | 277 |
|
| ... | ... |
@@ -379,7 +379,6 @@ func (nDB *NetworkDB) gossip() {
|
| 379 | 379 |
thisNodeNetworks := nDB.networks[nDB.config.NodeID] |
| 380 | 380 |
for nid := range thisNodeNetworks {
|
| 381 | 381 |
networkNodes[nid] = nDB.networkNodes[nid] |
| 382 |
- |
|
| 383 | 382 |
} |
| 384 | 383 |
printStats := time.Since(nDB.lastStatsTimestamp) >= nDB.config.StatsPrintPeriod |
| 385 | 384 |
printHealth := time.Since(nDB.lastHealthTimestamp) >= nDB.config.HealthPrintPeriod |
| ... | ... |
@@ -16,9 +16,12 @@ func (d *delegate) NodeMeta(limit int) []byte {
|
| 16 | 16 |
return []byte{}
|
| 17 | 17 |
} |
| 18 | 18 |
|
| 19 |
-func (nDB *NetworkDB) getNode(nEvent *NodeEvent) *node {
|
|
| 20 |
- nDB.Lock() |
|
| 21 |
- defer nDB.Unlock() |
|
| 19 |
+// getNode searches the node inside the tables |
|
| 20 |
+// returns true if the node was respectively in the active list, explicit node leave list or failed list |
|
| 21 |
+func (nDB *NetworkDB) getNode(nEvent *NodeEvent, extract bool) (bool, bool, bool, *node) {
|
|
| 22 |
+ var active bool |
|
| 23 |
+ var left bool |
|
| 24 |
+ var failed bool |
|
| 22 | 25 |
|
| 23 | 26 |
for _, nodes := range []map[string]*node{
|
| 24 | 27 |
nDB.failedNodes, |
| ... | ... |
@@ -26,35 +29,19 @@ func (nDB *NetworkDB) getNode(nEvent *NodeEvent) *node {
|
| 26 | 26 |
nDB.nodes, |
| 27 | 27 |
} {
|
| 28 | 28 |
if n, ok := nodes[nEvent.NodeName]; ok {
|
| 29 |
+ active = &nodes == &nDB.nodes |
|
| 30 |
+ left = &nodes == &nDB.leftNodes |
|
| 31 |
+ failed = &nodes == &nDB.failedNodes |
|
| 29 | 32 |
if n.ltime >= nEvent.LTime {
|
| 30 |
- return nil |
|
| 33 |
+ return active, left, failed, nil |
|
| 31 | 34 |
} |
| 32 |
- return n |
|
| 33 |
- } |
|
| 34 |
- } |
|
| 35 |
- return nil |
|
| 36 |
-} |
|
| 37 |
- |
|
| 38 |
-func (nDB *NetworkDB) checkAndGetNode(nEvent *NodeEvent) *node {
|
|
| 39 |
- nDB.Lock() |
|
| 40 |
- defer nDB.Unlock() |
|
| 41 |
- |
|
| 42 |
- for _, nodes := range []map[string]*node{
|
|
| 43 |
- nDB.failedNodes, |
|
| 44 |
- nDB.leftNodes, |
|
| 45 |
- nDB.nodes, |
|
| 46 |
- } {
|
|
| 47 |
- if n, ok := nodes[nEvent.NodeName]; ok {
|
|
| 48 |
- if n.ltime >= nEvent.LTime {
|
|
| 49 |
- return nil |
|
| 35 |
+ if extract {
|
|
| 36 |
+ delete(nodes, n.Name) |
|
| 50 | 37 |
} |
| 51 |
- |
|
| 52 |
- delete(nodes, n.Name) |
|
| 53 |
- return n |
|
| 38 |
+ return active, left, failed, n |
|
| 54 | 39 |
} |
| 55 | 40 |
} |
| 56 |
- |
|
| 57 |
- return nil |
|
| 41 |
+ return active, left, failed, nil |
|
| 58 | 42 |
} |
| 59 | 43 |
|
| 60 | 44 |
func (nDB *NetworkDB) handleNodeEvent(nEvent *NodeEvent) bool {
|
| ... | ... |
@@ -62,11 +49,14 @@ func (nDB *NetworkDB) handleNodeEvent(nEvent *NodeEvent) bool {
|
| 62 | 62 |
// time. |
| 63 | 63 |
nDB.networkClock.Witness(nEvent.LTime) |
| 64 | 64 |
|
| 65 |
- n := nDB.getNode(nEvent) |
|
| 65 |
+ nDB.RLock() |
|
| 66 |
+ active, left, _, n := nDB.getNode(nEvent, false) |
|
| 66 | 67 |
if n == nil {
|
| 68 |
+ nDB.RUnlock() |
|
| 67 | 69 |
return false |
| 68 | 70 |
} |
| 69 |
- // If its a node leave event for a manager and this is the only manager we |
|
| 71 |
+ nDB.RUnlock() |
|
| 72 |
+ // If it is a node leave event for a manager and this is the only manager we |
|
| 70 | 73 |
// know of we want the reconnect logic to kick in. In a single manager |
| 71 | 74 |
// cluster manager's gossip can't be bootstrapped unless some other node |
| 72 | 75 |
// connects to it. |
| ... | ... |
@@ -79,28 +69,38 @@ func (nDB *NetworkDB) handleNodeEvent(nEvent *NodeEvent) bool {
|
| 79 | 79 |
} |
| 80 | 80 |
} |
| 81 | 81 |
|
| 82 |
- n = nDB.checkAndGetNode(nEvent) |
|
| 83 |
- if n == nil {
|
|
| 84 |
- return false |
|
| 85 |
- } |
|
| 86 |
- |
|
| 87 | 82 |
n.ltime = nEvent.LTime |
| 88 | 83 |
|
| 89 | 84 |
switch nEvent.Type {
|
| 90 | 85 |
case NodeEventTypeJoin: |
| 86 |
+ if active {
|
|
| 87 |
+ // the node is already marked as active nothing to do |
|
| 88 |
+ return false |
|
| 89 |
+ } |
|
| 91 | 90 |
nDB.Lock() |
| 92 |
- _, found := nDB.nodes[n.Name] |
|
| 93 |
- nDB.nodes[n.Name] = n |
|
| 94 |
- nDB.Unlock() |
|
| 95 |
- if !found {
|
|
| 96 |
- logrus.Infof("Node join event for %s/%s", n.Name, n.Addr)
|
|
| 91 |
+ // Because the lock got released on the previous check we have to do it again and re verify the status of the node |
|
| 92 |
+ // All of this is to avoid a big lock on the function |
|
| 93 |
+ if active, _, _, n = nDB.getNode(nEvent, true); !active && n != nil {
|
|
| 94 |
+ n.reapTime = 0 |
|
| 95 |
+ nDB.nodes[n.Name] = n |
|
| 96 |
+ logrus.Infof("%v(%v): Node join event for %s/%s", nDB.config.Hostname, nDB.config.NodeID, n.Name, n.Addr)
|
|
| 97 | 97 |
} |
| 98 |
+ nDB.Unlock() |
|
| 98 | 99 |
return true |
| 99 | 100 |
case NodeEventTypeLeave: |
| 101 |
+ if left {
|
|
| 102 |
+ // the node is already marked as left nothing to do. |
|
| 103 |
+ return false |
|
| 104 |
+ } |
|
| 100 | 105 |
nDB.Lock() |
| 101 |
- nDB.leftNodes[n.Name] = n |
|
| 106 |
+ // Because the lock got released on the previous check we have to do it again and re verify the status of the node |
|
| 107 |
+ // All of this is to avoid a big lock on the function |
|
| 108 |
+ if _, left, _, n = nDB.getNode(nEvent, true); !left && n != nil {
|
|
| 109 |
+ n.reapTime = nodeReapInterval |
|
| 110 |
+ nDB.leftNodes[n.Name] = n |
|
| 111 |
+ logrus.Infof("%v(%v): Node leave event for %s/%s", nDB.config.Hostname, nDB.config.NodeID, n.Name, n.Addr)
|
|
| 112 |
+ } |
|
| 102 | 113 |
nDB.Unlock() |
| 103 |
- logrus.Infof("Node leave event for %s/%s", n.Name, n.Addr)
|
|
| 104 | 114 |
return true |
| 105 | 115 |
} |
| 106 | 116 |
|
| ... | ... |
@@ -140,7 +140,7 @@ func (nDB *NetworkDB) handleNetworkEvent(nEvent *NetworkEvent) bool {
|
| 140 | 140 |
n.ltime = nEvent.LTime |
| 141 | 141 |
n.leaving = nEvent.Type == NetworkEventTypeLeave |
| 142 | 142 |
if n.leaving {
|
| 143 |
- n.reapTime = reapNetworkInterval |
|
| 143 |
+ n.reapTime = nDB.config.reapNetworkInterval |
|
| 144 | 144 |
|
| 145 | 145 |
// The remote node is leaving the network, but not the gossip cluster. |
| 146 | 146 |
// Mark all its entries in deleted state, this will guarantee that |
| ... | ... |
@@ -162,6 +162,12 @@ func (nDB *NetworkDB) handleNetworkEvent(nEvent *NetworkEvent) bool {
|
| 162 | 162 |
return false |
| 163 | 163 |
} |
| 164 | 164 |
|
| 165 |
+ // If the node is not known from memberlist we cannot process save any state of it else if it actually |
|
| 166 |
+ // dies we won't receive any notification and we will remain stuck with it |
|
| 167 |
+ if _, ok := nDB.nodes[nEvent.NodeName]; !ok {
|
|
| 168 |
+ return false |
|
| 169 |
+ } |
|
| 170 |
+ |
|
| 165 | 171 |
// This remote network join is being seen the first time. |
| 166 | 172 |
nodeNetworks[nEvent.NetworkID] = &network{
|
| 167 | 173 |
id: nEvent.NetworkID, |
| ... | ... |
@@ -216,8 +222,9 @@ func (nDB *NetworkDB) handleTableEvent(tEvent *TableEvent) bool {
|
| 216 | 216 |
// This case can happen if the cluster is running different versions of the engine where the old version does not have the |
| 217 | 217 |
// field. If that is not the case, this can be a BUG |
| 218 | 218 |
if e.deleting && e.reapTime == 0 {
|
| 219 |
- logrus.Warnf("handleTableEvent object %+v has a 0 reapTime, is the cluster running the same docker engine version?", tEvent)
|
|
| 220 |
- e.reapTime = reapEntryInterval |
|
| 219 |
+ logrus.Warnf("%v(%v) handleTableEvent object %+v has a 0 reapTime, is the cluster running the same docker engine version?",
|
|
| 220 |
+ nDB.config.Hostname, nDB.config.NodeID, tEvent) |
|
| 221 |
+ e.reapTime = nDB.config.reapEntryInterval |
|
| 221 | 222 |
} |
| 222 | 223 |
|
| 223 | 224 |
nDB.Lock() |
| ... | ... |
@@ -229,7 +236,7 @@ func (nDB *NetworkDB) handleTableEvent(tEvent *TableEvent) bool {
|
| 229 | 229 |
// If the residual reapTime is lower or equal to 1/6 of the total reapTime don't bother broadcasting it around |
| 230 | 230 |
// most likely the cluster is already aware of it, if not who will sync with this node will catch the state too. |
| 231 | 231 |
// This also avoids that deletion of entries close to their garbage collection ends up circuling around forever |
| 232 |
- return e.reapTime > reapEntryInterval/6 |
|
| 232 |
+ return e.reapTime > nDB.config.reapEntryInterval/6 |
|
| 233 | 233 |
} |
| 234 | 234 |
|
| 235 | 235 |
var op opType |
| ... | ... |
@@ -465,7 +472,7 @@ func (d *delegate) MergeRemoteState(buf []byte, isJoin bool) {
|
| 465 | 465 |
var gMsg GossipMessage |
| 466 | 466 |
err := proto.Unmarshal(buf, &gMsg) |
| 467 | 467 |
if err != nil {
|
| 468 |
- logrus.Errorf("Error unmarshalling push pull messsage: %v", err)
|
|
| 468 |
+ logrus.Errorf("Error unmarshalling push pull message: %v", err)
|
|
| 469 | 469 |
return |
| 470 | 470 |
} |
| 471 | 471 |
|
| ... | ... |
@@ -21,10 +21,29 @@ func (e *eventDelegate) broadcastNodeEvent(addr net.IP, op opType) {
|
| 21 | 21 |
} |
| 22 | 22 |
} |
| 23 | 23 |
|
| 24 |
+func (e *eventDelegate) purgeReincarnation(mn *memberlist.Node) {
|
|
| 25 |
+ for name, node := range e.nDB.failedNodes {
|
|
| 26 |
+ if node.Addr.Equal(mn.Addr) {
|
|
| 27 |
+ logrus.Infof("Node %s/%s, is the new incarnation of the failed node %s/%s", mn.Name, mn.Addr, name, node.Addr)
|
|
| 28 |
+ delete(e.nDB.failedNodes, name) |
|
| 29 |
+ return |
|
| 30 |
+ } |
|
| 31 |
+ } |
|
| 32 |
+ |
|
| 33 |
+ for name, node := range e.nDB.leftNodes {
|
|
| 34 |
+ if node.Addr.Equal(mn.Addr) {
|
|
| 35 |
+ logrus.Infof("Node %s/%s, is the new incarnation of the shutdown node %s/%s", mn.Name, mn.Addr, name, node.Addr)
|
|
| 36 |
+ delete(e.nDB.leftNodes, name) |
|
| 37 |
+ return |
|
| 38 |
+ } |
|
| 39 |
+ } |
|
| 40 |
+} |
|
| 41 |
+ |
|
| 24 | 42 |
func (e *eventDelegate) NotifyJoin(mn *memberlist.Node) {
|
| 25 | 43 |
logrus.Infof("Node %s/%s, joined gossip cluster", mn.Name, mn.Addr)
|
| 26 | 44 |
e.broadcastNodeEvent(mn.Addr, opCreate) |
| 27 | 45 |
e.nDB.Lock() |
| 46 |
+ defer e.nDB.Unlock() |
|
| 28 | 47 |
// In case the node is rejoining after a failure or leave, |
| 29 | 48 |
// wait until an explicit join message arrives before adding |
| 30 | 49 |
// it to the nodes just to make sure this is not a stale |
| ... | ... |
@@ -32,12 +51,15 @@ func (e *eventDelegate) NotifyJoin(mn *memberlist.Node) {
|
| 32 | 32 |
_, fOk := e.nDB.failedNodes[mn.Name] |
| 33 | 33 |
_, lOk := e.nDB.leftNodes[mn.Name] |
| 34 | 34 |
if fOk || lOk {
|
| 35 |
- e.nDB.Unlock() |
|
| 36 | 35 |
return |
| 37 | 36 |
} |
| 38 | 37 |
|
| 38 |
+ // Every node has a unique ID |
|
| 39 |
+ // Check on the base of the IP address if the new node that joined is actually a new incarnation of a previous |
|
| 40 |
+ // failed or shutdown one |
|
| 41 |
+ e.purgeReincarnation(mn) |
|
| 42 |
+ |
|
| 39 | 43 |
e.nDB.nodes[mn.Name] = &node{Node: *mn}
|
| 40 |
- e.nDB.Unlock() |
|
| 41 | 44 |
logrus.Infof("Node %s/%s, added to nodes list", mn.Name, mn.Addr)
|
| 42 | 45 |
} |
| 43 | 46 |
|
| ... | ... |
@@ -49,18 +71,28 @@ func (e *eventDelegate) NotifyLeave(mn *memberlist.Node) {
|
| 49 | 49 |
// If the node was temporary down, deleting the entries will guarantee that the CREATE events will be accepted |
| 50 | 50 |
// If the node instead left because was going down, then it makes sense to just delete all its state |
| 51 | 51 |
e.nDB.Lock() |
| 52 |
+ defer e.nDB.Unlock() |
|
| 52 | 53 |
e.nDB.deleteNetworkEntriesForNode(mn.Name) |
| 53 | 54 |
e.nDB.deleteNodeTableEntries(mn.Name) |
| 54 | 55 |
if n, ok := e.nDB.nodes[mn.Name]; ok {
|
| 55 | 56 |
delete(e.nDB.nodes, mn.Name) |
| 56 | 57 |
|
| 58 |
+ // Check if a new incarnation of the same node already joined |
|
| 59 |
+ // In that case this node can simply be removed and no further action are needed |
|
| 60 |
+ for name, node := range e.nDB.nodes {
|
|
| 61 |
+ if node.Addr.Equal(mn.Addr) {
|
|
| 62 |
+ logrus.Infof("Node %s/%s, is the new incarnation of the failed node %s/%s", name, node.Addr, mn.Name, mn.Addr)
|
|
| 63 |
+ return |
|
| 64 |
+ } |
|
| 65 |
+ } |
|
| 66 |
+ |
|
| 57 | 67 |
// In case of node failure, keep retrying to reconnect every retryInterval (1sec) for nodeReapInterval (24h) |
| 58 | 68 |
// Explicit leave will have already removed the node from the list of nodes (nDB.nodes) and put it into the leftNodes map |
| 59 | 69 |
n.reapTime = nodeReapInterval |
| 60 | 70 |
e.nDB.failedNodes[mn.Name] = n |
| 61 | 71 |
failed = true |
| 62 | 72 |
} |
| 63 |
- e.nDB.Unlock() |
|
| 73 |
+ |
|
| 64 | 74 |
if failed {
|
| 65 | 75 |
logrus.Infof("Node %s/%s, added to failed nodes list", mn.Name, mn.Addr)
|
| 66 | 76 |
} |
| ... | ... |
@@ -181,6 +181,13 @@ type Config struct {
|
| 181 | 181 |
// be able to increase this to get more content into each gossip packet. |
| 182 | 182 |
PacketBufferSize int |
| 183 | 183 |
|
| 184 |
+ // reapEntryInterval duration of a deleted entry before being garbage collected |
|
| 185 |
+ reapEntryInterval time.Duration |
|
| 186 |
+ |
|
| 187 |
+ // reapNetworkInterval duration of a delted network before being garbage collected |
|
| 188 |
+ // NOTE this MUST always be higher than reapEntryInterval |
|
| 189 |
+ reapNetworkInterval time.Duration |
|
| 190 |
+ |
|
| 184 | 191 |
// StatsPrintPeriod the period to use to print queue stats |
| 185 | 192 |
// Default is 5min |
| 186 | 193 |
StatsPrintPeriod time.Duration |
| ... | ... |
@@ -220,12 +227,18 @@ func DefaultConfig() *Config {
|
| 220 | 220 |
PacketBufferSize: 1400, |
| 221 | 221 |
StatsPrintPeriod: 5 * time.Minute, |
| 222 | 222 |
HealthPrintPeriod: 1 * time.Minute, |
| 223 |
+ reapEntryInterval: 30 * time.Minute, |
|
| 223 | 224 |
} |
| 224 | 225 |
} |
| 225 | 226 |
|
| 226 | 227 |
// New creates a new instance of NetworkDB using the Config passed by |
| 227 | 228 |
// the caller. |
| 228 | 229 |
func New(c *Config) (*NetworkDB, error) {
|
| 230 |
+ // The garbage collection logic for entries leverage the presence of the network. |
|
| 231 |
+ // For this reason the expiration time of the network is put slightly higher than the entry expiration so that |
|
| 232 |
+ // there is at least 5 extra cycle to make sure that all the entries are properly deleted before deleting the network. |
|
| 233 |
+ c.reapNetworkInterval = c.reapEntryInterval + 5*reapPeriod |
|
| 234 |
+ |
|
| 229 | 235 |
nDB := &NetworkDB{
|
| 230 | 236 |
config: c, |
| 231 | 237 |
indexes: make(map[int]*radix.Tree), |
| ... | ... |
@@ -241,7 +254,7 @@ func New(c *Config) (*NetworkDB, error) {
|
| 241 | 241 |
nDB.indexes[byTable] = radix.New() |
| 242 | 242 |
nDB.indexes[byNetwork] = radix.New() |
| 243 | 243 |
|
| 244 |
- logrus.Debugf("New memberlist node - Node:%v will use memberlist nodeID:%v", c.Hostname, c.NodeID)
|
|
| 244 |
+ logrus.Infof("New memberlist node - Node:%v will use memberlist nodeID:%v with config:%+v", c.Hostname, c.NodeID, c)
|
|
| 245 | 245 |
if err := nDB.clusterInit(); err != nil {
|
| 246 | 246 |
return nil, err |
| 247 | 247 |
} |
| ... | ... |
@@ -297,6 +310,10 @@ func (nDB *NetworkDB) Peers(nid string) []PeerInfo {
|
| 297 | 297 |
Name: node.Name, |
| 298 | 298 |
IP: node.Addr.String(), |
| 299 | 299 |
}) |
| 300 |
+ } else {
|
|
| 301 |
+ // Added for testing purposes, this condition should never happen else mean that the network list |
|
| 302 |
+ // is out of sync with the node list |
|
| 303 |
+ peers = append(peers, PeerInfo{})
|
|
| 300 | 304 |
} |
| 301 | 305 |
} |
| 302 | 306 |
return peers |
| ... | ... |
@@ -414,7 +431,7 @@ func (nDB *NetworkDB) DeleteEntry(tname, nid, key string) error {
|
| 414 | 414 |
node: nDB.config.NodeID, |
| 415 | 415 |
value: value, |
| 416 | 416 |
deleting: true, |
| 417 |
- reapTime: reapEntryInterval, |
|
| 417 |
+ reapTime: nDB.config.reapEntryInterval, |
|
| 418 | 418 |
} |
| 419 | 419 |
|
| 420 | 420 |
if err := nDB.sendTableEvent(TableEventTypeDelete, nid, tname, key, entry); err != nil {
|
| ... | ... |
@@ -487,7 +504,7 @@ func (nDB *NetworkDB) deleteNodeNetworkEntries(nid, node string) {
|
| 487 | 487 |
node: oldEntry.node, |
| 488 | 488 |
value: oldEntry.value, |
| 489 | 489 |
deleting: true, |
| 490 |
- reapTime: reapEntryInterval, |
|
| 490 |
+ reapTime: nDB.config.reapEntryInterval, |
|
| 491 | 491 |
} |
| 492 | 492 |
|
| 493 | 493 |
// we arrived at this point in 2 cases: |
| ... | ... |
@@ -580,6 +597,9 @@ func (nDB *NetworkDB) JoinNetwork(nid string) error {
|
| 580 | 580 |
nodeNetworks[nid] = &network{id: nid, ltime: ltime, entriesNumber: entries}
|
| 581 | 581 |
nodeNetworks[nid].tableBroadcasts = &memberlist.TransmitLimitedQueue{
|
| 582 | 582 |
NumNodes: func() int {
|
| 583 |
+ //TODO fcrisciani this can be optimized maybe avoiding the lock? |
|
| 584 |
+ // this call is done each GetBroadcasts call to evaluate the number of |
|
| 585 |
+ // replicas for the message |
|
| 583 | 586 |
nDB.RLock() |
| 584 | 587 |
defer nDB.RUnlock() |
| 585 | 588 |
return len(nDB.networkNodes[nid]) |
| ... | ... |
@@ -635,7 +655,7 @@ func (nDB *NetworkDB) LeaveNetwork(nid string) error {
|
| 635 | 635 |
|
| 636 | 636 |
logrus.Debugf("%v(%v): leaving network %s", nDB.config.Hostname, nDB.config.NodeID, nid)
|
| 637 | 637 |
n.ltime = ltime |
| 638 |
- n.reapTime = reapNetworkInterval |
|
| 638 |
+ n.reapTime = nDB.config.reapNetworkInterval |
|
| 639 | 639 |
n.leaving = true |
| 640 | 640 |
return nil |
| 641 | 641 |
} |
| ... | ... |
@@ -5,7 +5,9 @@ import ( |
| 5 | 5 |
"net/http" |
| 6 | 6 |
"strings" |
| 7 | 7 |
|
| 8 |
+ stackdump "github.com/docker/docker/pkg/signal" |
|
| 8 | 9 |
"github.com/docker/libnetwork/diagnose" |
| 10 |
+ "github.com/sirupsen/logrus" |
|
| 9 | 11 |
) |
| 10 | 12 |
|
| 11 | 13 |
const ( |
| ... | ... |
@@ -24,6 +26,7 @@ var NetDbPaths2Func = map[string]diagnose.HTTPHandlerFunc{
|
| 24 | 24 |
"/deleteentry": dbDeleteEntry, |
| 25 | 25 |
"/getentry": dbGetEntry, |
| 26 | 26 |
"/gettable": dbGetTable, |
| 27 |
+ "/dump": dbStackTrace, |
|
| 27 | 28 |
} |
| 28 | 29 |
|
| 29 | 30 |
func dbJoin(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
| ... | ... |
@@ -240,3 +243,12 @@ func dbGetTable(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
| 240 | 240 |
} |
| 241 | 241 |
} |
| 242 | 242 |
} |
| 243 |
+ |
|
| 244 |
+func dbStackTrace(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
|
| 245 |
+ path, err := stackdump.DumpStacks("/tmp/")
|
|
| 246 |
+ if err != nil {
|
|
| 247 |
+ logrus.WithError(err).Error("failed to write goroutines dump")
|
|
| 248 |
+ } else {
|
|
| 249 |
+ fmt.Fprintf(w, "goroutine stacks written to %s", path) |
|
| 250 |
+ } |
|
| 251 |
+} |
| 5 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,24 +0,0 @@ |
| 1 |
-package osl |
|
| 2 |
- |
|
| 3 |
-// NewSandbox provides a new sandbox instance created in an os specific way |
|
| 4 |
-// provided a key which uniquely identifies the sandbox |
|
| 5 |
-func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) {
|
|
| 6 |
- return nil, nil |
|
| 7 |
-} |
|
| 8 |
- |
|
| 9 |
-// GenerateKey generates a sandbox key based on the passed |
|
| 10 |
-// container id. |
|
| 11 |
-func GenerateKey(containerID string) string {
|
|
| 12 |
- maxLen := 12 |
|
| 13 |
- |
|
| 14 |
- if len(containerID) < maxLen {
|
|
| 15 |
- maxLen = len(containerID) |
|
| 16 |
- } |
|
| 17 |
- |
|
| 18 |
- return containerID[:maxLen] |
|
| 19 |
-} |
|
| 20 |
- |
|
| 21 |
-// InitOSContext initializes OS context while configuring network resources |
|
| 22 |
-func InitOSContext() func() {
|
|
| 23 |
- return func() {}
|
|
| 24 |
-} |
| 17 | 17 |
deleted file mode 100644 |
| ... | ... |
@@ -1,34 +0,0 @@ |
| 1 |
-package portmapper |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "net" |
|
| 5 |
- "os/exec" |
|
| 6 |
- "strconv" |
|
| 7 |
-) |
|
| 8 |
- |
|
| 9 |
-func newProxyCommand(proto string, hostIP net.IP, hostPort int, containerIP net.IP, containerPort int, proxyPath string) (userlandProxy, error) {
|
|
| 10 |
- path := proxyPath |
|
| 11 |
- if proxyPath == "" {
|
|
| 12 |
- cmd, err := exec.LookPath(userlandProxyCommandName) |
|
| 13 |
- if err != nil {
|
|
| 14 |
- return nil, err |
|
| 15 |
- } |
|
| 16 |
- path = cmd |
|
| 17 |
- } |
|
| 18 |
- |
|
| 19 |
- args := []string{
|
|
| 20 |
- path, |
|
| 21 |
- "-proto", proto, |
|
| 22 |
- "-host-ip", hostIP.String(), |
|
| 23 |
- "-host-port", strconv.Itoa(hostPort), |
|
| 24 |
- "-container-ip", containerIP.String(), |
|
| 25 |
- "-container-port", strconv.Itoa(containerPort), |
|
| 26 |
- } |
|
| 27 |
- |
|
| 28 |
- return &proxyCommand{
|
|
| 29 |
- cmd: &exec.Cmd{
|
|
| 30 |
- Path: path, |
|
| 31 |
- Args: args, |
|
| 32 |
- }, |
|
| 33 |
- }, nil |
|
| 34 |
-} |
| 35 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,45 +0,0 @@ |
| 1 |
-// +build solaris |
|
| 2 |
- |
|
| 3 |
-package libnetwork |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "io" |
|
| 7 |
- "net" |
|
| 8 |
- |
|
| 9 |
- "github.com/docker/libnetwork/types" |
|
| 10 |
-) |
|
| 11 |
- |
|
| 12 |
-// processSetKeyReexec is a private function that must be called only on an reexec path |
|
| 13 |
-// It expects 3 args { [0] = "libnetwork-setkey", [1] = <container-id>, [2] = <controller-id> }
|
|
| 14 |
-// It also expects libcontainer.State as a json string in <stdin> |
|
| 15 |
-// Refer to https://github.com/opencontainers/runc/pull/160/ for more information |
|
| 16 |
-func processSetKeyReexec() {
|
|
| 17 |
-} |
|
| 18 |
- |
|
| 19 |
-// SetExternalKey provides a convenient way to set an External key to a sandbox |
|
| 20 |
-func SetExternalKey(controllerID string, containerID string, key string) error {
|
|
| 21 |
- return types.NotImplementedErrorf("SetExternalKey isn't supported on non linux systems")
|
|
| 22 |
-} |
|
| 23 |
- |
|
| 24 |
-func sendKey(c net.Conn, data setKeyData) error {
|
|
| 25 |
- return types.NotImplementedErrorf("sendKey isn't supported on non linux systems")
|
|
| 26 |
-} |
|
| 27 |
- |
|
| 28 |
-func processReturn(r io.Reader) error {
|
|
| 29 |
- return types.NotImplementedErrorf("processReturn isn't supported on non linux systems")
|
|
| 30 |
-} |
|
| 31 |
- |
|
| 32 |
-// no-op on non linux systems |
|
| 33 |
-func (c *controller) startExternalKeyListener() error {
|
|
| 34 |
- return nil |
|
| 35 |
-} |
|
| 36 |
- |
|
| 37 |
-func (c *controller) acceptClientConnections(sock string, l net.Listener) {
|
|
| 38 |
-} |
|
| 39 |
- |
|
| 40 |
-func (c *controller) processExternalKey(conn net.Conn) error {
|
|
| 41 |
- return types.NotImplementedErrorf("processExternalKey isn't supported on non linux systems")
|
|
| 42 |
-} |
|
| 43 |
- |
|
| 44 |
-func (c *controller) stopExternalKeyListener() {
|
|
| 45 |
-} |
| ... | ... |
@@ -256,6 +256,7 @@ retry: |
| 256 | 256 |
if err := cs.GetObject(datastore.Key(kvObject.Key()...), kvObject); err != nil {
|
| 257 | 257 |
return fmt.Errorf("could not update the kvobject to latest when trying to delete: %v", err)
|
| 258 | 258 |
} |
| 259 |
+ logrus.Errorf("Error (%v) deleting object %v, retrying....", err, kvObject.Key())
|
|
| 259 | 260 |
goto retry |
| 260 | 261 |
} |
| 261 | 262 |
return err |
| ... | ... |
@@ -1,44 +1,53 @@ |
| 1 |
-github.com/Azure/go-ansiterm 19f72df4d05d31cbe1c56bfc8045c96babff6c7e |
|
| 1 |
+github.com/Azure/go-ansiterm d6e3b3328b783f23731bc4d058875b0371ff8109 |
|
| 2 | 2 |
github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060 |
| 3 |
-github.com/Microsoft/go-winio ce2922f643c8fd76b46cadc7f404a06282678b34 |
|
| 4 |
-github.com/Microsoft/hcsshim v0.6.3 |
|
| 3 |
+github.com/Microsoft/go-winio v0.4.5 |
|
| 4 |
+github.com/Microsoft/hcsshim v0.6.5 |
|
| 5 | 5 |
github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec |
| 6 | 6 |
github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 |
| 7 |
-github.com/boltdb/bolt c6ba97b89e0454fec9aa92e1d33a4e2c5fc1f631 |
|
| 7 |
+github.com/boltdb/bolt fff57c100f4dea1905678da7e90d92429dff2904 |
|
| 8 | 8 |
github.com/codegangsta/cli a65b733b303f0055f8d324d805f393cd3e7a7904 |
| 9 |
-github.com/coreos/etcd 925d1d74cec8c3b169c52fd4b2dc234a35934fce |
|
| 10 |
-github.com/coreos/go-systemd b4a58d95188dd092ae20072bac14cece0e67c388 |
|
| 9 |
+github.com/containerd/console 84eeaae905fa414d03e07bcd6c8d3f19e7cf180e |
|
| 10 |
+github.com/containerd/continuity 22694c680ee48fb8f50015b44618517e2bde77e8 |
|
| 11 |
+github.com/coreos/etcd v3.2.1 |
|
| 12 |
+github.com/coreos/go-semver v0.2.0 |
|
| 13 |
+github.com/coreos/go-systemd v4 |
|
| 11 | 14 |
github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d |
| 12 | 15 |
|
| 13 |
-github.com/docker/docker 2cac43e3573893cf8fd816e0ad5615426acb87f4 https://github.com/dmcgowan/docker.git |
|
| 16 |
+github.com/docker/docker a3efe9722f34af5cf4443fe3a5c4e4e3e0457b54 |
|
| 14 | 17 |
github.com/docker/go-connections 3ede32e2033de7505e6500d6c868c2b9ed9f169d |
| 15 | 18 |
github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 |
| 16 |
-github.com/docker/go-units 8e2d4523730c73120e10d4652f36ad6010998f4e |
|
| 19 |
+github.com/docker/go-units 9e638d38cf6977a37a8ea0078f3ee75a7cdb2dd1 |
|
| 17 | 20 |
github.com/docker/libkv 1d8431073ae03cdaedb198a89722f3aab6d418ef |
| 18 | 21 |
|
| 19 |
-github.com/godbus/dbus 5f6efc7ef2759c81b7ba876593971bfce311eab3 |
|
| 20 |
-github.com/gogo/protobuf 8d70fb3182befc465c4a1eac8ad4d38ff49778e2 |
|
| 21 |
-github.com/golang/protobuf f7137ae6b19afbfd61a94b746fda3b3fe0491874 |
|
| 22 |
-github.com/gorilla/context 215affda49addc4c8ef7e2534915df2c8c35c6cd |
|
| 23 |
-github.com/gorilla/mux 8096f47503459bcc74d1f4c487b7e6e42e5746b5 |
|
| 24 |
-github.com/hashicorp/consul 954aec66231b79c161a4122b023fbcad13047f79 |
|
| 22 |
+github.com/godbus/dbus v4.0.0 |
|
| 23 |
+github.com/gogo/protobuf v0.4 |
|
| 24 |
+github.com/golang/protobuf 7a211bcf3bce0e3f1d74f9894916e6f116ae83b4 |
|
| 25 |
+github.com/gorilla/context v1.1 |
|
| 26 |
+github.com/gorilla/mux v1.1 |
|
| 27 |
+github.com/hashicorp/consul v0.5.2 |
|
| 25 | 28 |
github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b |
| 26 |
-github.com/hashicorp/go-multierror 2167c8ec40776024589f483a6b836489e47e1049 |
|
| 29 |
+github.com/hashicorp/go-multierror fcdddc395df1ddf4247c69bd436e84cfa0733f7e |
|
| 27 | 30 |
github.com/hashicorp/memberlist v0.1.0 |
| 28 | 31 |
github.com/sean-/seed e2103e2c35297fb7e17febb81e49b312087a2372 |
| 29 | 32 |
github.com/hashicorp/go-sockaddr acd314c5781ea706c710d9ea70069fd2e110d61d |
| 30 | 33 |
github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870 |
| 31 |
-github.com/mattn/go-shellwords 525bedee691b5a8df547cb5cf9f86b7fb1883e24 |
|
| 32 |
-github.com/miekg/dns d27455715200c7d3e321a1e5cadb27c9ee0b0f02 |
|
| 33 |
-github.com/opencontainers/runc 8694d576ea3ce3c9e2c804b7f91b4e1e9a575d1c https://github.com/dmcgowan/runc.git |
|
| 34 |
+github.com/mattn/go-shellwords v1.0.3 |
|
| 35 |
+github.com/miekg/dns 75e6e86cc601825c5dbcd4e0c209eab180997cd7 |
|
| 36 |
+github.com/mrunalp/fileutils ed869b029674c0e9ce4c0dfa781405c2d9946d08 |
|
| 37 |
+github.com/opencontainers/go-digest a6d0ee40d4207ea02364bd3b9e8e77b9159ba1eb |
|
| 38 |
+github.com/opencontainers/image-spec 372ad780f63454fbbbbcc7cf80e5b90245c13e13 |
|
| 39 |
+github.com/opencontainers/runc 0351df1c5a66838d0c392b4ac4cf9450de844e2d |
|
| 40 |
+github.com/opencontainers/runtime-spec v1.0.0 |
|
| 41 |
+github.com/opencontainers/selinux v1.0.0-rc1 |
|
| 34 | 42 |
github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374 |
| 35 |
-github.com/seccomp/libseccomp-golang 1b506fc7c24eec5a3693cdcbed40d9c226cfc6a1 |
|
| 36 |
-github.com/sirupsen/logrus v1.0.1 |
|
| 43 |
+github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0 |
|
| 44 |
+github.com/sirupsen/logrus v1.0.3 |
|
| 37 | 45 |
github.com/stretchr/testify dab07ac62d4905d3e48d17dc549c684ac3b7c15a |
| 38 |
-github.com/syndtr/gocapability 2c00daeb6c3b45114c80ac44119e7b8801fdd852 |
|
| 46 |
+github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16 |
|
| 39 | 47 |
github.com/ugorji/go f1f1a805ed361a0e078bb537e4ea78cd37dcf065 |
| 40 | 48 |
github.com/vishvananda/netlink bd6d5de5ccef2d66b0a26177928d0d8895d7f969 |
| 41 | 49 |
github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25 |
| 42 |
-golang.org/x/net c427ad74c6d7a814201695e9ffde0c5d400a7674 |
|
| 43 |
-golang.org/x/sys 8f0908ab3b2457e2e15403d3697c9ef5cb4b57a9 |
|
| 50 |
+golang.org/x/crypto 558b6879de74bc843225cde5686419267ff707ca |
|
| 51 |
+golang.org/x/net 7dcfb8076726a3fdd9353b6b8a1f1b6be6811bd6 |
|
| 52 |
+golang.org/x/sys 07c182904dbd53199946ba614a412c61d3c548f5 |
|
| 44 | 53 |
github.com/pkg/errors 839d9e913e063e28dfd0e6c7b7512793e0a48be9 |