func (c *controller) LeaveAll(id string) error { c.Lock() sData, ok := c.sandboxes[sandbox.GenerateKey(id)] c.Unlock() if !ok { return fmt.Errorf("could not find sandbox for container id %s", id) } sData.Lock() eps := make([]*endpoint, len(sData.endpoints)) for i, ep := range sData.endpoints { eps[i] = ep } sData.Unlock() for _, ep := range eps { if err := ep.Leave(id); err != nil { logrus.Warnf("Failed leaving endpoint id %s: %v\n", ep.ID(), err) } } sData.sandbox().Destroy() c.Lock() delete(c.sandboxes, sandbox.GenerateKey(id)) c.Unlock() return nil }
func TestSandboxAddEmpty(t *testing.T) { ctrlr := createEmptyCtrlr() ep := createEmptyEndpoint() if _, err := ctrlr.sandboxAdd(sandbox.GenerateKey("sandbox1"), true, ep); err != nil { t.Fatal(err) } ctrlr.sandboxRm(sandbox.GenerateKey("sandbox1"), ep) ctrlr.LeaveAll("sandbox1") if len(ctrlr.sandboxes) != 0 { t.Fatalf("controller sandboxes is not empty. len = %d", len(ctrlr.sandboxes)) } sandbox.GC() }
func (n *network) initSandbox() error { n.Lock() n.initEpoch++ n.Unlock() sbox, err := sandbox.NewSandbox( sandbox.GenerateKey(fmt.Sprintf("%d-", n.initEpoch)+string(n.id)), true) if err != nil { return fmt.Errorf("could not create network sandbox: %v", err) } // Add a bridge inside the namespace if err := sbox.AddInterface("bridge1", "br", sbox.InterfaceOptions().Address(bridgeIP), sbox.InterfaceOptions().Bridge(true)); err != nil { return fmt.Errorf("could not create bridge inside the network sandbox: %v", err) } vxlanName, err := createVxlan(n.vxlanID()) if err != nil { return err } if err := sbox.AddInterface(vxlanName, "vxlan", sbox.InterfaceOptions().Master("bridge1")); err != nil { return fmt.Errorf("could not add vxlan interface inside the network sandbox: %v", err) } n.vxlanName = vxlanName n.setSandbox(sbox) n.driver.peerDbUpdateSandbox(n.id) var nlSock *nl.NetlinkSocket sbox.InvokeFunc(func() { nlSock, err = nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_NEIGH) if err != nil { err = fmt.Errorf("failed to subscribe to neighbor group netlink messages") } }) go n.watchMiss(nlSock) return nil }
func TestSandboxAddSamePrio(t *testing.T) { ctrlr := createEmptyCtrlr() ep1 := createEmptyEndpoint() ep2 := createEmptyEndpoint() ep1.network = &network{name: "aaa"} ep2.network = &network{name: "bbb"} sKey := sandbox.GenerateKey("sandbox1") if _, err := ctrlr.sandboxAdd(sKey, true, ep1); err != nil { t.Fatal(err) } if _, err := ctrlr.sandboxAdd(sKey, true, ep2); err != nil { t.Fatal(err) } if ctrlr.sandboxes[sKey].endpoints[0] != ep1 { t.Fatal("Expected ep1 to be at the top of the heap. But did not find ep1 at the top of the heap") } ctrlr.sandboxRm(sKey, ep1) if ctrlr.sandboxes[sKey].endpoints[0] != ep2 { t.Fatal("Expected ep2 to be at the top of the heap after removing ep3. But did not find ep2 at the top of the heap") } ctrlr.sandboxRm(sKey, ep2) if err := ctrlr.LeaveAll("sandbox1"); err != nil { t.Fatal(err) } if len(ctrlr.sandboxes) != 0 { t.Fatalf("controller sandboxes is not empty. len = %d", len(ctrlr.sandboxes)) } sandbox.GC() }
func (ep *endpoint) Join(containerID string, options ...EndpointOption) error { var err error if containerID == "" { return InvalidContainerIDError(containerID) } ep.joinLeaveStart() defer func() { ep.joinLeaveEnd() }() ep.Lock() if ep.container != nil { ep.Unlock() return ErrInvalidJoin{} } ep.container = &containerInfo{ id: containerID, config: containerConfig{ hostsPathConfig: hostsPathConfig{ extraHosts: []extraHost{}, parentUpdates: []parentUpdate{}, }, }} ep.joinInfo = &endpointJoinInfo{} container := ep.container network := ep.network epid := ep.id ep.Unlock() defer func() { if err != nil { ep.Lock() ep.container = nil ep.Unlock() } }() network.Lock() driver := network.driver nid := network.id ctrlr := network.ctrlr network.Unlock() ep.processOptions(options...) sboxKey := sandbox.GenerateKey(containerID) if container.config.useDefaultSandBox { sboxKey = sandbox.GenerateKey("default") } err = driver.Join(nid, epid, sboxKey, ep, container.config.generic) if err != nil { return err } defer func() { if err != nil { if err = driver.Leave(nid, epid); err != nil { log.Warnf("driver leave failed while rolling back join: %v", err) } } }() err = ep.buildHostsFiles() if err != nil { return err } err = ep.updateParentHosts() if err != nil { return err } err = ep.setupDNS() if err != nil { return err } sb, err := ctrlr.sandboxAdd(sboxKey, !container.config.useDefaultSandBox, ep) if err != nil { return fmt.Errorf("failed sandbox add: %v", err) } defer func() { if err != nil { ctrlr.sandboxRm(sboxKey, ep) } }() if err := network.ctrlr.updateEndpointToStore(ep); err != nil { return err } container.data.SandboxKey = sb.Key() return nil }
func (ep *endpoint) Join(containerID string, options ...EndpointOption) (*ContainerData, error) { var err error if containerID == "" { return nil, InvalidContainerIDError(containerID) } ep.joinLeaveStart() defer ep.joinLeaveEnd() ep.Lock() if ep.container != nil { ep.Unlock() return nil, ErrInvalidJoin{} } ep.container = &containerInfo{ id: containerID, config: containerConfig{ hostsPathConfig: hostsPathConfig{ extraHosts: []extraHost{}, parentUpdates: []parentUpdate{}, }, }} ep.joinInfo = &endpointJoinInfo{} container := ep.container network := ep.network epid := ep.id joinInfo := ep.joinInfo ifaces := ep.iFaces ep.Unlock() defer func() { ep.Lock() if err != nil { ep.container = nil } ep.Unlock() }() network.Lock() driver := network.driver nid := network.id ctrlr := network.ctrlr network.Unlock() ep.processOptions(options...) sboxKey := sandbox.GenerateKey(containerID) if container.config.useDefaultSandBox { sboxKey = sandbox.GenerateKey("default") } err = driver.Join(nid, epid, sboxKey, ep, container.config.generic) if err != nil { return nil, err } err = ep.buildHostsFiles() if err != nil { return nil, err } err = ep.updateParentHosts() if err != nil { return nil, err } err = ep.setupDNS() if err != nil { return nil, err } sb, err := ctrlr.sandboxAdd(sboxKey, !container.config.useDefaultSandBox) if err != nil { return nil, err } defer func() { if err != nil { ctrlr.sandboxRm(sboxKey) } }() for _, i := range ifaces { iface := &sandbox.Interface{ SrcName: i.srcName, DstName: i.dstPrefix, Address: &i.addr, } if i.addrv6.IP.To16() != nil { iface.AddressIPv6 = &i.addrv6 } err = sb.AddInterface(iface) if err != nil { return nil, err } } err = sb.SetGateway(joinInfo.gw) if err != nil { return nil, err } err = sb.SetGatewayIPv6(joinInfo.gw6) if err != nil { return nil, err } container.data.SandboxKey = sb.Key() cData := container.data return &cData, nil }
func TestSandboxAddMultiPrio(t *testing.T) { ctrlr := createEmptyCtrlr() ep1 := createEmptyEndpoint() ep2 := createEmptyEndpoint() ep3 := createEmptyEndpoint() ep1.container.config.prio = 1 ep2.container.config.prio = 2 ep3.container.config.prio = 3 sKey := sandbox.GenerateKey("sandbox1") if _, err := ctrlr.sandboxAdd(sKey, true, ep1); err != nil { t.Fatal(err) } if _, err := ctrlr.sandboxAdd(sKey, true, ep2); err != nil { t.Fatal(err) } if _, err := ctrlr.sandboxAdd(sKey, true, ep3); err != nil { t.Fatal(err) } if ctrlr.sandboxes[sKey].endpoints[0] != ep3 { t.Fatal("Expected ep3 to be at the top of the heap. But did not find ep3 at the top of the heap") } ctrlr.sandboxRm(sKey, ep3) if ctrlr.sandboxes[sKey].endpoints[0] != ep2 { t.Fatal("Expected ep2 to be at the top of the heap after removing ep3. But did not find ep2 at the top of the heap") } ctrlr.sandboxRm(sKey, ep2) if ctrlr.sandboxes[sKey].endpoints[0] != ep1 { t.Fatal("Expected ep1 to be at the top of the heap after removing ep2. But did not find ep1 at the top of the heap") } // Re-add ep3 back if _, err := ctrlr.sandboxAdd(sKey, true, ep3); err != nil { t.Fatal(err) } if ctrlr.sandboxes[sKey].endpoints[0] != ep3 { t.Fatal("Expected ep3 to be at the top of the heap after adding ep3 back. But did not find ep3 at the top of the heap") } ctrlr.sandboxRm(sKey, ep3) ctrlr.sandboxRm(sKey, ep1) if err := ctrlr.LeaveAll("sandbox1"); err != nil { t.Fatal(err) } if len(ctrlr.sandboxes) != 0 { t.Fatalf("controller sandboxes is not empty. len = %d", len(ctrlr.sandboxes)) } sandbox.GC() }