mirror of
https://github.com/clearlinux/libnetwork.git
synced 2026-09-03 12:21:32 +00:00
Driver api refactor
Refactored the driver api so that is aligns well with the design
of endpoint lifecycle becoming decoupled from the container lifecycle.
Introduced go interfaces to obtain address information during CreateEndpoint.
Go interfaces are also used to get data from driver during join.
This sort of deisgn hides the libnetwork specific type details from drivers.
Another adjustment is to provide a list of interfaces during CreateEndpoint. The
goal of this is many-fold:
* To indicate to the driver that IP address has been assigned by some other
entity (like a user wanting to use their own static IP for an endpoint/container)
and asking the driver to honor this. Driver may reject this configuration
and return an error but it may not try to allocate an IP address and override
the passed one.
* To indicate to the driver that IP address has already been allocated once
for this endpoint by an instance of the same driver in some docker host
in the cluster and this is merely a notification about that endpoint and the
allocated resources.
* In case the list of interfaces is empty the driver is required to allocate and
assign IP addresses for this endpoint.
Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
This commit is contained in:
+96
-58
@@ -1,6 +1,7 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -22,6 +23,7 @@ const (
|
||||
vethLen = 7
|
||||
containerVeth = "eth0"
|
||||
maxAllocatePortAttempts = 10
|
||||
ifaceID = 1
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -371,44 +373,52 @@ func (d *driver) DeleteNetwork(nid types.UUID) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *driver) CreateEndpoint(nid, eid types.UUID, epOptions map[string]interface{}) (*sandbox.Info, error) {
|
||||
func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointInfo, epOptions map[string]interface{}) error {
|
||||
var (
|
||||
ipv6Addr *net.IPNet
|
||||
err error
|
||||
)
|
||||
|
||||
if epInfo == nil {
|
||||
return errors.New("invalid endpoint info passed")
|
||||
}
|
||||
|
||||
if len(epInfo.Interfaces()) != 0 {
|
||||
return errors.New("non empty interface list passed to bridge(local) driver")
|
||||
}
|
||||
|
||||
// Get the network handler and make sure it exists
|
||||
d.Lock()
|
||||
n := d.network
|
||||
config := n.config
|
||||
d.Unlock()
|
||||
if n == nil {
|
||||
return nil, driverapi.ErrNoNetwork
|
||||
return driverapi.ErrNoNetwork
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
n.Lock()
|
||||
if n.id != nid {
|
||||
n.Unlock()
|
||||
return nil, InvalidNetworkIDError(nid)
|
||||
return InvalidNetworkIDError(nid)
|
||||
}
|
||||
n.Unlock()
|
||||
|
||||
// Check if endpoint id is good and retrieve correspondent endpoint
|
||||
ep, err := n.getEndpoint(eid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// Endpoint with that id exists either on desired or other sandbox
|
||||
if ep != nil {
|
||||
return nil, driverapi.ErrEndpointExists
|
||||
return driverapi.ErrEndpointExists
|
||||
}
|
||||
|
||||
// Try to convert the options to endpoint configuration
|
||||
epConfig, err := parseEndpointOptions(epOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// Create and add the endpoint
|
||||
@@ -429,13 +439,13 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epOptions map[string]interf
|
||||
// Generate a name for what will be the host side pipe interface
|
||||
name1, err := generateIfaceName()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// Generate a name for what will be the sandbox side pipe interface
|
||||
name2, err := generateIfaceName()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// Generate and add the interface pipe host <-> sandbox
|
||||
@@ -443,13 +453,13 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epOptions map[string]interf
|
||||
LinkAttrs: netlink.LinkAttrs{Name: name1, TxQLen: 0},
|
||||
PeerName: name2}
|
||||
if err = netlink.LinkAdd(veth); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// Get the host side pipe interface handler
|
||||
host, err := netlink.LinkByName(name1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -460,7 +470,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epOptions map[string]interf
|
||||
// Get the sandbox side pipe interface handler
|
||||
sbox, err := netlink.LinkByName(name2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -472,7 +482,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epOptions map[string]interf
|
||||
mac := electMacAddress(epConfig)
|
||||
err = netlink.LinkSetHardwareAddr(sbox, mac)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
endpoint.macAddress = mac
|
||||
|
||||
@@ -480,28 +490,29 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epOptions map[string]interf
|
||||
if config.Mtu != 0 {
|
||||
err = netlink.LinkSetMTU(host, config.Mtu)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
err = netlink.LinkSetMTU(sbox, config.Mtu)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Attach host side pipe interface into the bridge
|
||||
if err = netlink.LinkSetMaster(host,
|
||||
&netlink.Bridge{LinkAttrs: netlink.LinkAttrs{Name: config.BridgeName}}); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// v4 address for the sandbox side pipe interface
|
||||
ip4, err := ipAllocator.RequestIP(n.bridge.bridgeIPv4, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
ipv4Addr := &net.IPNet{IP: ip4, Mask: n.bridge.bridgeIPv4.Mask}
|
||||
|
||||
// v6 address for the sandbox side pipe interface
|
||||
ipv6Addr = &net.IPNet{}
|
||||
if config.EnableIPv6 {
|
||||
var ip6 net.IP
|
||||
|
||||
@@ -521,7 +532,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epOptions map[string]interf
|
||||
|
||||
ip6, err := ipAllocator.RequestIP(network, ip6)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
ipv6Addr = &net.IPNet{IP: ip6, Mask: network.Mask}
|
||||
@@ -533,26 +544,25 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epOptions map[string]interf
|
||||
intf.DstName = containerVeth
|
||||
intf.Address = ipv4Addr
|
||||
|
||||
if config.EnableIPv6 {
|
||||
intf.AddressIPv6 = ipv6Addr
|
||||
}
|
||||
|
||||
// Store the interface in endpoint, this is needed for cleanup on DeleteEndpoint()
|
||||
endpoint.intf = intf
|
||||
|
||||
// Generate the sandbox info to return
|
||||
sinfo := &sandbox.Info{Interfaces: []*sandbox.Interface{intf}}
|
||||
|
||||
// Set the default gateway(s) for the sandbox
|
||||
sinfo.Gateway = n.bridge.gatewayIPv4
|
||||
if config.EnableIPv6 {
|
||||
intf.AddressIPv6 = ipv6Addr
|
||||
sinfo.GatewayIPv6 = n.bridge.gatewayIPv6
|
||||
err = epInfo.AddInterface(ifaceID, endpoint.macAddress, *ipv4Addr, *ipv6Addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Program any required port mapping and store them in the endpoint
|
||||
endpoint.portMapping, err = allocatePorts(epConfig, sinfo, config.DefaultBindingIP)
|
||||
endpoint.portMapping, err = allocatePorts(epConfig, intf, config.DefaultBindingIP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
return sinfo, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) DeleteEndpoint(nid, eid types.UUID) error {
|
||||
@@ -628,7 +638,7 @@ func (d *driver) DeleteEndpoint(nid, eid types.UUID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) EndpointInfo(nid, eid types.UUID) (map[string]interface{}, error) {
|
||||
func (d *driver) EndpointOperInfo(nid, eid types.UUID) (map[string]interface{}, error) {
|
||||
// Get the network handler and make sure it exists
|
||||
d.Lock()
|
||||
n := d.network
|
||||
@@ -673,40 +683,12 @@ func (d *driver) EndpointInfo(nid, eid types.UUID) (map[string]interface{}, erro
|
||||
}
|
||||
|
||||
// Join method is invoked when a Sandbox is attached to an endpoint.
|
||||
func (d *driver) Join(nid, eid types.UUID, sboxKey string, options map[string]interface{}) (*driverapi.JoinInfo, error) {
|
||||
network, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !network.config.EnableICC {
|
||||
return nil, d.link(nid, eid, options, true)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||
func (d *driver) Leave(nid, eid types.UUID, options map[string]interface{}) error {
|
||||
func (d *driver) Join(nid, eid types.UUID, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
||||
network, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !network.config.EnableICC {
|
||||
return d.link(nid, eid, options, false)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) link(nid, eid types.UUID, options map[string]interface{}, enable bool) error {
|
||||
var cc *ContainerConfiguration
|
||||
|
||||
network, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
endpoint, err := network.getEndpoint(eid)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -716,6 +698,62 @@ func (d *driver) link(nid, eid types.UUID, options map[string]interface{}, enabl
|
||||
return EndpointNotFoundError(eid)
|
||||
}
|
||||
|
||||
for _, iNames := range jinfo.InterfaceNames() {
|
||||
// Make sure to set names on the correct interface ID.
|
||||
if iNames.ID() == ifaceID {
|
||||
err = iNames.SetNames(endpoint.intf.SrcName, endpoint.intf.DstName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = jinfo.SetGateway(network.bridge.gatewayIPv4)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = jinfo.SetGatewayIPv6(network.bridge.gatewayIPv6)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !network.config.EnableICC {
|
||||
return d.link(network, endpoint, options, true)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||
func (d *driver) Leave(nid, eid types.UUID) error {
|
||||
network, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
endpoint, err := network.getEndpoint(eid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if endpoint == nil {
|
||||
return EndpointNotFoundError(eid)
|
||||
}
|
||||
|
||||
if !network.config.EnableICC {
|
||||
return d.link(network, endpoint, nil, false)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, options map[string]interface{}, enable bool) error {
|
||||
var (
|
||||
cc *ContainerConfiguration
|
||||
err error
|
||||
)
|
||||
|
||||
if enable {
|
||||
cc, err = parseContainerOptions(options)
|
||||
if err != nil {
|
||||
|
||||
+120
-19
@@ -7,6 +7,7 @@ import (
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/iptables"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
@@ -70,6 +71,91 @@ func TestCreateFail(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type testInterface struct {
|
||||
id int
|
||||
mac net.HardwareAddr
|
||||
addr net.IPNet
|
||||
addrv6 net.IPNet
|
||||
srcName string
|
||||
dstName string
|
||||
}
|
||||
|
||||
type testEndpoint struct {
|
||||
ifaces []*testInterface
|
||||
gw net.IP
|
||||
gw6 net.IP
|
||||
hostsPath string
|
||||
resolvConfPath string
|
||||
}
|
||||
|
||||
func (te *testEndpoint) Interfaces() []driverapi.InterfaceInfo {
|
||||
iList := make([]driverapi.InterfaceInfo, len(te.ifaces))
|
||||
|
||||
for i, iface := range te.ifaces {
|
||||
iList[i] = iface
|
||||
}
|
||||
|
||||
return iList
|
||||
}
|
||||
|
||||
func (te *testEndpoint) AddInterface(id int, mac net.HardwareAddr, ipv4 net.IPNet, ipv6 net.IPNet) error {
|
||||
iface := &testInterface{id: id, addr: ipv4, addrv6: ipv6}
|
||||
te.ifaces = append(te.ifaces, iface)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *testInterface) ID() int {
|
||||
return i.id
|
||||
}
|
||||
|
||||
func (i *testInterface) MacAddress() net.HardwareAddr {
|
||||
return i.mac
|
||||
}
|
||||
|
||||
func (i *testInterface) Address() net.IPNet {
|
||||
return i.addr
|
||||
}
|
||||
|
||||
func (i *testInterface) AddressIPv6() net.IPNet {
|
||||
return i.addrv6
|
||||
}
|
||||
|
||||
func (i *testInterface) SetNames(srcName string, dstName string) error {
|
||||
i.srcName = srcName
|
||||
i.dstName = dstName
|
||||
return nil
|
||||
}
|
||||
|
||||
func (te *testEndpoint) InterfaceNames() []driverapi.InterfaceNameInfo {
|
||||
iList := make([]driverapi.InterfaceNameInfo, len(te.ifaces))
|
||||
|
||||
for i, iface := range te.ifaces {
|
||||
iList[i] = iface
|
||||
}
|
||||
|
||||
return iList
|
||||
}
|
||||
|
||||
func (te *testEndpoint) SetGateway(gw net.IP) error {
|
||||
te.gw = gw
|
||||
return nil
|
||||
}
|
||||
|
||||
func (te *testEndpoint) SetGatewayIPv6(gw6 net.IP) error {
|
||||
te.gw6 = gw6
|
||||
return nil
|
||||
}
|
||||
|
||||
func (te *testEndpoint) SetHostsPath(path string) error {
|
||||
te.hostsPath = path
|
||||
return nil
|
||||
}
|
||||
|
||||
func (te *testEndpoint) SetResolvConfPath(path string) error {
|
||||
te.resolvConfPath = path
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestQueryEndpointInfo(t *testing.T) {
|
||||
defer netutils.SetupTestNetNS(t)()
|
||||
d := newDriver()
|
||||
@@ -92,13 +178,14 @@ func TestQueryEndpointInfo(t *testing.T) {
|
||||
epOptions := make(map[string]interface{})
|
||||
epOptions[netlabel.PortMap] = portMappings
|
||||
|
||||
_, err = d.CreateEndpoint("net1", "ep1", epOptions)
|
||||
te := &testEndpoint{ifaces: []*testInterface{}}
|
||||
err = d.CreateEndpoint("net1", "ep1", te, epOptions)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create an endpoint : %s", err.Error())
|
||||
}
|
||||
|
||||
ep, _ := dd.network.endpoints["ep1"]
|
||||
data, err := d.EndpointInfo(dd.network.id, ep.id)
|
||||
data, err := d.EndpointOperInfo(dd.network.id, ep.id)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to ask for endpoint operational data: %v", err)
|
||||
}
|
||||
@@ -143,12 +230,18 @@ func TestCreateLinkWithOptions(t *testing.T) {
|
||||
epOptions := make(map[string]interface{})
|
||||
epOptions[netlabel.MacAddress] = mac
|
||||
|
||||
sinfo, err := d.CreateEndpoint("net1", "ep", epOptions)
|
||||
te := &testEndpoint{ifaces: []*testInterface{}}
|
||||
err = d.CreateEndpoint("net1", "ep", te, epOptions)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a link: %s", err.Error())
|
||||
t.Fatalf("Failed to create an endpoint: %s", err.Error())
|
||||
}
|
||||
|
||||
ifaceName := sinfo.Interfaces[0].SrcName
|
||||
err = d.Join("net1", "ep", "sbox", te, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to join the endpoint: %v", err)
|
||||
}
|
||||
|
||||
ifaceName := te.ifaces[0].srcName
|
||||
veth, err := netlink.LinkByName(ifaceName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -197,23 +290,25 @@ func TestLinkContainers(t *testing.T) {
|
||||
epOptions := make(map[string]interface{})
|
||||
epOptions[netlabel.ExposedPorts] = exposedPorts
|
||||
|
||||
sinfo, err := d.CreateEndpoint("net1", "ep1", epOptions)
|
||||
te1 := &testEndpoint{ifaces: []*testInterface{}}
|
||||
err = d.CreateEndpoint("net1", "ep1", te1, epOptions)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create an endpoint : %s", err.Error())
|
||||
}
|
||||
|
||||
addr1 := sinfo.Interfaces[0].Address
|
||||
if addr1 == nil {
|
||||
addr1 := te1.ifaces[0].addr
|
||||
if addr1.IP.To4() == nil {
|
||||
t.Fatalf("No Ipv4 address assigned to the endpoint: ep1")
|
||||
}
|
||||
|
||||
sinfo, err = d.CreateEndpoint("net1", "ep2", nil)
|
||||
te2 := &testEndpoint{ifaces: []*testInterface{}}
|
||||
err = d.CreateEndpoint("net1", "ep2", te2, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create an endpoint : %s", err.Error())
|
||||
}
|
||||
|
||||
addr2 := sinfo.Interfaces[0].Address
|
||||
if addr2 == nil {
|
||||
addr2 := te2.ifaces[0].addr
|
||||
if addr2.IP.To4() == nil {
|
||||
t.Fatalf("No Ipv4 address assigned to the endpoint: ep2")
|
||||
}
|
||||
|
||||
@@ -222,7 +317,7 @@ func TestLinkContainers(t *testing.T) {
|
||||
genericOption = make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = cConfig
|
||||
|
||||
_, err = d.Join("net1", "ep2", "", genericOption)
|
||||
err = d.Join("net1", "ep2", "", te2, genericOption)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to link ep1 and ep2")
|
||||
}
|
||||
@@ -243,7 +338,7 @@ func TestLinkContainers(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
err = d.Leave("net1", "ep2", genericOption)
|
||||
err = d.Leave("net1", "ep2")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to unlink ep1 and ep2")
|
||||
}
|
||||
@@ -270,7 +365,7 @@ func TestLinkContainers(t *testing.T) {
|
||||
genericOption = make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = cConfig
|
||||
|
||||
_, err = d.Join("net1", "ep2", "", genericOption)
|
||||
err = d.Join("net1", "ep2", "", te2, genericOption)
|
||||
if err != nil {
|
||||
out, err = iptables.Raw("-L", DockerChain)
|
||||
for _, pm := range exposedPorts {
|
||||
@@ -406,16 +501,22 @@ func TestSetDefaultGw(t *testing.T) {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
sinfo, err := d.CreateEndpoint("dummy", "ep", nil)
|
||||
te := &testEndpoint{ifaces: []*testInterface{}}
|
||||
err = d.CreateEndpoint("dummy", "ep", te, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create endpoint: %v", err)
|
||||
}
|
||||
|
||||
if !gw4.Equal(sinfo.Gateway) {
|
||||
t.Fatalf("Failed to configure default gateway. Expected %v. Found %v", gw4, sinfo.Gateway)
|
||||
err = d.Join("dummy", "ep", "sbox", te, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to join endpoint: %v", err)
|
||||
}
|
||||
|
||||
if !gw6.Equal(sinfo.GatewayIPv6) {
|
||||
t.Fatalf("Failed to configure default gateway. Expected %v. Found %v", gw6, sinfo.GatewayIPv6)
|
||||
if !gw4.Equal(te.gw) {
|
||||
t.Fatalf("Failed to configure default gateway. Expected %v. Found %v", gw4, te.gw)
|
||||
}
|
||||
|
||||
if !gw6.Equal(te.gw6) {
|
||||
t.Fatalf("Failed to configure default gateway. Expected %v. Found %v", gw6, te.gw6)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,8 @@ func TestLinkCreate(t *testing.T) {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
sinfo, err := d.CreateEndpoint("dummy", "", nil)
|
||||
te := &testEndpoint{ifaces: []*testInterface{}}
|
||||
err = d.CreateEndpoint("dummy", "", te, nil)
|
||||
if err != nil {
|
||||
if _, ok := err.(InvalidEndpointIDError); !ok {
|
||||
t.Fatalf("Failed with a wrong error :%s", err.Error())
|
||||
@@ -38,13 +39,18 @@ func TestLinkCreate(t *testing.T) {
|
||||
}
|
||||
|
||||
// Good endpoint creation
|
||||
sinfo, err = d.CreateEndpoint("dummy", "ep", nil)
|
||||
err = d.CreateEndpoint("dummy", "ep", te, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a link: %s", err.Error())
|
||||
}
|
||||
|
||||
err = d.Join("dummy", "ep", "sbox", te, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a link: %s", err.Error())
|
||||
}
|
||||
|
||||
// Verify sbox endoint interface inherited MTU value from bridge config
|
||||
sboxLnk, err := netlink.LinkByName(sinfo.Interfaces[0].SrcName)
|
||||
sboxLnk, err := netlink.LinkByName(te.ifaces[0].srcName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -54,44 +60,44 @@ func TestLinkCreate(t *testing.T) {
|
||||
// TODO: if we could get peer name from (sboxLnk.(*netlink.Veth)).PeerName
|
||||
// then we could check the MTU on hostLnk as well.
|
||||
|
||||
_, err = d.CreateEndpoint("dummy", "ep", nil)
|
||||
te1 := &testEndpoint{ifaces: []*testInterface{}}
|
||||
err = d.CreateEndpoint("dummy", "ep", te1, nil)
|
||||
if err == nil {
|
||||
t.Fatalf("Failed to detect duplicate endpoint id on same network")
|
||||
}
|
||||
|
||||
interfaces := sinfo.Interfaces
|
||||
if len(interfaces) != 1 {
|
||||
t.Fatalf("Expected exactly one interface. Instead got %d interface(s)", len(interfaces))
|
||||
if len(te.ifaces) != 1 {
|
||||
t.Fatalf("Expected exactly one interface. Instead got %d interface(s)", len(te.ifaces))
|
||||
}
|
||||
|
||||
if interfaces[0].DstName == "" {
|
||||
if te.ifaces[0].dstName == "" {
|
||||
t.Fatal("Invalid Dstname returned")
|
||||
}
|
||||
|
||||
_, err = netlink.LinkByName(interfaces[0].SrcName)
|
||||
_, err = netlink.LinkByName(te.ifaces[0].srcName)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not find source link %s: %v", interfaces[0].SrcName, err)
|
||||
t.Fatalf("Could not find source link %s: %v", te.ifaces[0].srcName, err)
|
||||
}
|
||||
|
||||
n := dr.network
|
||||
ip := interfaces[0].Address.IP
|
||||
ip := te.ifaces[0].addr.IP
|
||||
if !n.bridge.bridgeIPv4.Contains(ip) {
|
||||
t.Fatalf("IP %s is not a valid ip in the subnet %s", ip.String(), n.bridge.bridgeIPv4.String())
|
||||
}
|
||||
|
||||
ip6 := interfaces[0].AddressIPv6.IP
|
||||
ip6 := te.ifaces[0].addrv6.IP
|
||||
if !n.bridge.bridgeIPv6.Contains(ip6) {
|
||||
t.Fatalf("IP %s is not a valid ip in the subnet %s", ip6.String(), bridgeIPv6.String())
|
||||
}
|
||||
|
||||
if !sinfo.Gateway.Equal(n.bridge.bridgeIPv4.IP) {
|
||||
if !te.gw.Equal(n.bridge.bridgeIPv4.IP) {
|
||||
t.Fatalf("Invalid default gateway. Expected %s. Got %s", n.bridge.bridgeIPv4.IP.String(),
|
||||
sinfo.Gateway.String())
|
||||
te.gw.String())
|
||||
}
|
||||
|
||||
if !sinfo.GatewayIPv6.Equal(n.bridge.bridgeIPv6.IP) {
|
||||
if !te.gw6.Equal(n.bridge.bridgeIPv6.IP) {
|
||||
t.Fatalf("Invalid default gateway for IPv6. Expected %s. Got %s", n.bridge.bridgeIPv6.IP.String(),
|
||||
sinfo.GatewayIPv6.String())
|
||||
te.gw6.String())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,12 +116,14 @@ func TestLinkCreateTwo(t *testing.T) {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
_, err = d.CreateEndpoint("dummy", "ep", nil)
|
||||
te1 := &testEndpoint{ifaces: []*testInterface{}}
|
||||
err = d.CreateEndpoint("dummy", "ep", te1, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a link: %s", err.Error())
|
||||
}
|
||||
|
||||
_, err = d.CreateEndpoint("dummy", "ep", nil)
|
||||
te2 := &testEndpoint{ifaces: []*testInterface{}}
|
||||
err = d.CreateEndpoint("dummy", "ep", te2, nil)
|
||||
if err != nil {
|
||||
if err != driverapi.ErrEndpointExists {
|
||||
t.Fatalf("Failed with a wrong error :%s", err.Error())
|
||||
@@ -139,18 +147,19 @@ func TestLinkCreateNoEnableIPv6(t *testing.T) {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
sinfo, err := d.CreateEndpoint("dummy", "ep", nil)
|
||||
te := &testEndpoint{ifaces: []*testInterface{}}
|
||||
err = d.CreateEndpoint("dummy", "ep", te, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a link: %s", err.Error())
|
||||
}
|
||||
|
||||
interfaces := sinfo.Interfaces
|
||||
if interfaces[0].AddressIPv6 != nil {
|
||||
t.Fatalf("Expectd IPv6 address to be nil when IPv6 is not enabled. Got IPv6 = %s", interfaces[0].AddressIPv6.String())
|
||||
interfaces := te.ifaces
|
||||
if interfaces[0].addrv6.IP.To16() != nil {
|
||||
t.Fatalf("Expectd IPv6 address to be nil when IPv6 is not enabled. Got IPv6 = %s", interfaces[0].addrv6.String())
|
||||
}
|
||||
|
||||
if sinfo.GatewayIPv6 != nil {
|
||||
t.Fatalf("Expected GatewayIPv6 to be nil when IPv6 is not enabled. Got GatewayIPv6 = %s", sinfo.GatewayIPv6.String())
|
||||
if te.gw6.To16() != nil {
|
||||
t.Fatalf("Expected GatewayIPv6 to be nil when IPv6 is not enabled. Got GatewayIPv6 = %s", te.gw6.String())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,7 +178,8 @@ func TestLinkDelete(t *testing.T) {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
_, err = d.CreateEndpoint("dummy", "ep1", nil)
|
||||
te := &testEndpoint{ifaces: []*testInterface{}}
|
||||
err = d.CreateEndpoint("dummy", "ep1", te, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a link: %s", err.Error())
|
||||
}
|
||||
@@ -187,9 +197,4 @@ func TestLinkDelete(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = d.DeleteEndpoint("dummy", "ep1")
|
||||
if err == nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ var (
|
||||
defaultBindingIP = net.IPv4(0, 0, 0, 0)
|
||||
)
|
||||
|
||||
func allocatePorts(epConfig *EndpointConfiguration, sinfo *sandbox.Info, reqDefBindIP net.IP) ([]netutils.PortBinding, error) {
|
||||
func allocatePorts(epConfig *EndpointConfiguration, intf *sandbox.Interface, reqDefBindIP net.IP) ([]netutils.PortBinding, error) {
|
||||
if epConfig == nil || epConfig.PortBindings == nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -25,7 +25,7 @@ func allocatePorts(epConfig *EndpointConfiguration, sinfo *sandbox.Info, reqDefB
|
||||
defHostIP = reqDefBindIP
|
||||
}
|
||||
|
||||
return allocatePortsInternal(epConfig.PortBindings, sinfo.Interfaces[0].Address.IP, defHostIP)
|
||||
return allocatePortsInternal(epConfig.PortBindings, intf.Address.IP, defHostIP)
|
||||
}
|
||||
|
||||
func allocatePortsInternal(bindings []netutils.PortBinding, containerIP, defHostIP net.IP) ([]netutils.PortBinding, error) {
|
||||
|
||||
@@ -39,7 +39,8 @@ func TestPortMappingConfig(t *testing.T) {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
_, err = d.CreateEndpoint("dummy", "ep1", epOptions)
|
||||
te := &testEndpoint{ifaces: []*testInterface{}}
|
||||
err = d.CreateEndpoint("dummy", "ep1", te, epOptions)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create the endpoint: %s", err.Error())
|
||||
}
|
||||
|
||||
+6
-11
@@ -2,7 +2,6 @@ package host
|
||||
|
||||
import (
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/sandbox"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
@@ -27,29 +26,25 @@ func (d *driver) DeleteNetwork(nid types.UUID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) CreateEndpoint(nid, eid types.UUID, epOptions map[string]interface{}) (*sandbox.Info, error) {
|
||||
return nil, nil
|
||||
func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointInfo, epOptions map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) DeleteEndpoint(nid, eid types.UUID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) EndpointInfo(nid, eid types.UUID) (map[string]interface{}, error) {
|
||||
func (d *driver) EndpointOperInfo(nid, eid types.UUID) (map[string]interface{}, error) {
|
||||
return make(map[string]interface{}, 0), nil
|
||||
}
|
||||
|
||||
// Join method is invoked when a Sandbox is attached to an endpoint.
|
||||
func (d *driver) Join(nid, eid types.UUID, sboxKey string, options map[string]interface{}) (*driverapi.JoinInfo, error) {
|
||||
jInfo := &driverapi.JoinInfo{
|
||||
HostsPath: "/etc/hosts",
|
||||
}
|
||||
|
||||
return jInfo, nil
|
||||
func (d *driver) Join(nid, eid types.UUID, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
||||
return (jinfo.SetHostsPath("/etc/hosts"))
|
||||
}
|
||||
|
||||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||
func (d *driver) Leave(nid, eid types.UUID, options map[string]interface{}) error {
|
||||
func (d *driver) Leave(nid, eid types.UUID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package null
|
||||
|
||||
import (
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/sandbox"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
@@ -27,25 +26,25 @@ func (d *driver) DeleteNetwork(nid types.UUID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) CreateEndpoint(nid, eid types.UUID, epOptions map[string]interface{}) (*sandbox.Info, error) {
|
||||
return nil, nil
|
||||
func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointInfo, epOptions map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) DeleteEndpoint(nid, eid types.UUID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) EndpointInfo(nid, eid types.UUID) (map[string]interface{}, error) {
|
||||
func (d *driver) EndpointOperInfo(nid, eid types.UUID) (map[string]interface{}, error) {
|
||||
return make(map[string]interface{}, 0), nil
|
||||
}
|
||||
|
||||
// Join method is invoked when a Sandbox is attached to an endpoint.
|
||||
func (d *driver) Join(nid, eid types.UUID, sboxKey string, options map[string]interface{}) (*driverapi.JoinInfo, error) {
|
||||
return nil, nil
|
||||
func (d *driver) Join(nid, eid types.UUID, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||
func (d *driver) Leave(nid, eid types.UUID, options map[string]interface{}) error {
|
||||
func (d *driver) Leave(nid, eid types.UUID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/pkg/plugins"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/sandbox"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
@@ -43,25 +42,25 @@ func (d *driver) DeleteNetwork(nid types.UUID) error {
|
||||
return driverapi.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (d *driver) CreateEndpoint(nid, eid types.UUID, epOptions map[string]interface{}) (*sandbox.Info, error) {
|
||||
return nil, driverapi.ErrNotImplemented
|
||||
func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointInfo, epOptions map[string]interface{}) error {
|
||||
return driverapi.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (d *driver) DeleteEndpoint(nid, eid types.UUID) error {
|
||||
return driverapi.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (d *driver) EndpointInfo(nid, eid types.UUID) (map[string]interface{}, error) {
|
||||
func (d *driver) EndpointOperInfo(nid, eid types.UUID) (map[string]interface{}, error) {
|
||||
return nil, driverapi.ErrNotImplemented
|
||||
}
|
||||
|
||||
// Join method is invoked when a Sandbox is attached to an endpoint.
|
||||
func (d *driver) Join(nid, eid types.UUID, sboxKey string, options map[string]interface{}) (*driverapi.JoinInfo, error) {
|
||||
return nil, driverapi.ErrNotImplemented
|
||||
func (d *driver) Join(nid, eid types.UUID, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
||||
return driverapi.ErrNotImplemented
|
||||
}
|
||||
|
||||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||
func (d *driver) Leave(nid, eid types.UUID, options map[string]interface{}) error {
|
||||
func (d *driver) Leave(nid, eid types.UUID) error {
|
||||
return driverapi.ErrNotImplemented
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user