1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #1145 from mrjana/overlay

Make overlay driver work without a kv store
This commit is contained in:
Santhosh Manohar 2016-04-29 08:21:51 -07:00
commit 982d591456
5 changed files with 116 additions and 47 deletions

View file

@ -3,6 +3,7 @@ package overlay
import (
"fmt"
"net"
"strings"
log "github.com/Sirupsen/logrus"
"github.com/docker/libnetwork/driverapi"
@ -104,11 +105,55 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
d.peerDbAdd(nid, eid, ep.addr.IP, ep.addr.Mask, ep.mac,
net.ParseIP(d.bindAddress), true)
if err := jinfo.AddTableEntry(ovPeerTable, eid, []byte(fmt.Sprintf("%s,%s,%s", ep.addr, ep.mac, d.bindAddress))); err != nil {
log.Errorf("overlay: Failed adding table entry to joininfo: %v", err)
}
d.pushLocalEndpointEvent("join", nid, eid)
return nil
}
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
if tableName != ovPeerTable {
log.Errorf("Unexpected table notification for table %s received", tableName)
return
}
eid := key
values := strings.Split(string(value), ",")
if len(values) < 3 {
log.Errorf("Invalid value %s received through event notify", string(value))
return
}
addr, err := types.ParseCIDR(values[0])
if err != nil {
log.Errorf("Invalid peer IP %s received in event notify", values[0])
return
}
mac, err := net.ParseMAC(values[1])
if err != nil {
log.Errorf("Invalid mac %s received in event notify", values[1])
return
}
vtep := net.ParseIP(values[2])
if vtep == nil {
log.Errorf("Invalid VTEP %s received in event notify", values[2])
return
}
if etype == driverapi.Delete {
d.peerDelete(nid, eid, addr.IP, addr.Mask, mac, vtep, true)
return
}
d.peerAdd(nid, eid, addr.IP, addr.Mask, mac, vtep, true)
}
// Leave method is invoked when a Sandbox detaches from an endpoint.
func (d *driver) Leave(nid, eid string) error {
if err := validateID(nid, eid); err != nil {

View file

@ -6,6 +6,7 @@ import (
"net"
"os"
"path/filepath"
"strconv"
"strings"
"sync"
"syscall"
@ -13,6 +14,7 @@ import (
"github.com/Sirupsen/logrus"
"github.com/docker/libnetwork/datastore"
"github.com/docker/libnetwork/driverapi"
"github.com/docker/libnetwork/netlabel"
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/osl"
"github.com/docker/libnetwork/resolvconf"
@ -67,9 +69,6 @@ func (d *driver) NetworkFree(id string) error {
return types.NotImplementedErrorf("not implemented")
}
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
}
func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
if id == "" {
return fmt.Errorf("invalid network id")
@ -92,12 +91,40 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d
subnets: []*subnet{},
}
for _, ipd := range ipV4Data {
vnis := make([]uint32, 0, len(ipV4Data))
if gval, ok := option[netlabel.GenericData]; ok {
optMap := gval.(map[string]string)
if val, ok := optMap[netlabel.OverlayVxlanIDList]; ok {
logrus.Debugf("overlay: Received vxlan IDs: %s", val)
vniStrings := strings.Split(val, ",")
for _, vniStr := range vniStrings {
vni, err := strconv.Atoi(vniStr)
if err != nil {
return fmt.Errorf("invalid vxlan id value %q passed", vniStr)
}
vnis = append(vnis, uint32(vni))
}
}
}
// If we are getting vnis from libnetwork, either we get for
// all subnets or none.
if len(vnis) != 0 && len(vnis) < len(ipV4Data) {
return fmt.Errorf("insufficient vnis(%d) passed to overlay", len(vnis))
}
for i, ipd := range ipV4Data {
s := &subnet{
subnetIP: ipd.Pool,
gwIP: ipd.Gateway,
once: &sync.Once{},
}
if len(vnis) != 0 {
s.vni = vnis[i]
}
n.subnets = append(n.subnets, s)
}
@ -105,8 +132,13 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d
return fmt.Errorf("failed to update data store for network %v: %v", n.id, err)
}
d.addNetwork(n)
if nInfo != nil {
if err := nInfo.TableEventRegister(ovPeerTable); err != nil {
return err
}
}
d.addNetwork(n)
return nil
}
@ -255,11 +287,21 @@ func setHostMode() {
}
func (n *network) generateVxlanName(s *subnet) string {
return "vx-" + fmt.Sprintf("%06x", n.vxlanID(s)) + "-" + n.id[:5]
id := n.id
if len(n.id) > 5 {
id = n.id[:5]
}
return "vx-" + fmt.Sprintf("%06x", n.vxlanID(s)) + "-" + id
}
func (n *network) generateBridgeName(s *subnet) string {
return "ov-" + fmt.Sprintf("%06x", n.vxlanID(s)) + "-" + n.id[:5]
id := n.id
if len(n.id) > 5 {
id = n.id[:5]
}
return "ov-" + fmt.Sprintf("%06x", n.vxlanID(s)) + "-" + id
}
func isOverlap(nw *net.IPNet) bool {
@ -587,32 +629,38 @@ func (n *network) DataScope() string {
}
func (n *network) writeToStore() error {
if n.driver.store == nil {
return nil
}
return n.driver.store.PutObjectAtomic(n)
}
func (n *network) releaseVxlanID() error {
if n.driver.store == nil {
return fmt.Errorf("no datastore configured. cannot release vxlan id")
}
if len(n.subnets) == 0 {
return nil
}
if err := n.driver.store.DeleteObjectAtomic(n); err != nil {
if err == datastore.ErrKeyModified || err == datastore.ErrKeyNotFound {
// In both the above cases we can safely assume that the key has been removed by some other
// instance and so simply get out of here
return nil
}
if n.driver.store != nil {
if err := n.driver.store.DeleteObjectAtomic(n); err != nil {
if err == datastore.ErrKeyModified || err == datastore.ErrKeyNotFound {
// In both the above cases we can safely assume that the key has been removed by some other
// instance and so simply get out of here
return nil
}
return fmt.Errorf("failed to delete network to vxlan id map: %v", err)
return fmt.Errorf("failed to delete network to vxlan id map: %v", err)
}
}
for _, s := range n.subnets {
n.driver.vxlanIdm.Release(uint64(n.vxlanID(s)))
if n.driver.vxlanIdm != nil {
n.driver.vxlanIdm.Release(uint64(n.vxlanID(s)))
}
n.setVxlanID(s, 0)
}
return nil
}
@ -623,7 +671,7 @@ func (n *network) obtainVxlanID(s *subnet) error {
}
if n.driver.store == nil {
return fmt.Errorf("no datastore configured. cannot obtain vxlan id")
return fmt.Errorf("no valid vxlan id and no datastore configured, cannot obtain vxlan id")
}
for {

View file

@ -88,7 +88,7 @@ func Fini(drv driverapi.Driver) {
func (d *driver) configure() error {
if d.store == nil {
return types.NoServiceErrorf("datastore is not available")
return nil
}
if d.vxlanIdm == nil {

View file

@ -8,7 +8,6 @@ import (
"github.com/docker/libnetwork/discoverapi"
"github.com/docker/libnetwork/driverapi"
_ "github.com/docker/libnetwork/testutils"
"github.com/docker/libnetwork/types"
)
type driverTester struct {
@ -24,14 +23,6 @@ func setupDriver(t *testing.T) *driverTester {
t.Fatal(err)
}
err := dt.d.configure()
if err == nil {
t.Fatalf("Failed to detect nil store")
}
if _, ok := err.(types.NoServiceError); !ok {
t.Fatalf("Unexpected error type: %v", err)
}
iface, err := net.InterfaceByName("eth0")
if err != nil {
t.Fatal(err)
@ -93,23 +84,6 @@ func TestOverlayFiniWithoutConfig(t *testing.T) {
cleanupDriver(t, dt)
}
func TestOverlayNilConfig(t *testing.T) {
dt := &driverTester{t: t}
if err := Init(dt, nil); err != nil {
t.Fatal(err)
}
err := dt.d.configure()
if err == nil {
t.Fatalf("Failed to detect nil store")
}
if _, ok := err.(types.NoServiceError); !ok {
t.Fatalf("Unexpected error type: %v", err)
}
cleanupDriver(t, dt)
}
func TestOverlayConfig(t *testing.T) {
dt := setupDriver(t)

View file

@ -7,6 +7,8 @@ import (
"syscall"
)
const ovPeerTable = "overlay_peer_table"
type peerKey struct {
peerIP net.IP
peerMac net.HardwareAddr