mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #84 from aboch/mao
Libnetwork bridge to handle --mac-address option
This commit is contained in:
commit
914ad10ea4
7 changed files with 97 additions and 20 deletions
|
@ -35,7 +35,7 @@ func main() {
|
|||
// settings will be used for container infos (inspect and such), as well as
|
||||
// iptables rules for port publishing. This info is contained or accessible
|
||||
// from the returned endpoint.
|
||||
ep, err := network.CreateEndpoint("Endpoint1", networkNamespace.Key(), "")
|
||||
ep, err := network.CreateEndpoint("Endpoint1", networkNamespace.Key(), nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -41,9 +41,15 @@ type Configuration struct {
|
|||
AllowNonDefaultBridge bool
|
||||
}
|
||||
|
||||
// EndpointConfiguration represents the user specified configuration for the sandbox endpoint
|
||||
type EndpointConfiguration struct {
|
||||
MacAddress net.HardwareAddr
|
||||
}
|
||||
|
||||
type bridgeEndpoint struct {
|
||||
id types.UUID
|
||||
port *sandbox.Interface
|
||||
config *EndpointConfiguration // User specified parameters
|
||||
}
|
||||
|
||||
type bridgeNetwork struct {
|
||||
|
@ -239,7 +245,7 @@ func (d *driver) DeleteNetwork(nid types.UUID) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (d *driver) CreateEndpoint(nid, eid types.UUID, sboxKey string, epOption interface{}) (*sandbox.Info, error) {
|
||||
func (d *driver) CreateEndpoint(nid, eid types.UUID, sboxKey string, epOptions interface{}) (*sandbox.Info, error) {
|
||||
var (
|
||||
ipv6Addr *net.IPNet
|
||||
err error
|
||||
|
@ -285,8 +291,14 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, sboxKey string, epOption in
|
|||
return nil, driverapi.ErrEndpointExists
|
||||
}
|
||||
|
||||
// Try to convert the options to endpoint configuration
|
||||
epConfig, err := parseEndpointOptions(epOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create and add the endpoint
|
||||
endpoint := &bridgeEndpoint{id: eid}
|
||||
endpoint := &bridgeEndpoint{id: eid, config: epConfig}
|
||||
n.endpoints[sboxKey] = endpoint
|
||||
n.Unlock()
|
||||
|
||||
|
@ -335,6 +347,15 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, sboxKey string, epOption in
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Add user specified attributes
|
||||
if epConfig != nil && epConfig.MacAddress != nil {
|
||||
err = netlink.LinkSetHardwareAddr(sbox, epConfig.MacAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
netlink.LinkDel(sbox)
|
||||
|
@ -347,14 +368,14 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, sboxKey string, epOption in
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Reuqest a v4 address for the sandbox side pipe interface
|
||||
// v4 address for the sandbox side pipe interface
|
||||
ip4, err := ipAllocator.RequestIP(n.bridge.bridgeIPv4, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ipv4Addr := &net.IPNet{IP: ip4, Mask: n.bridge.bridgeIPv4.Mask}
|
||||
|
||||
// Request a v6 address for the sandbox side pipe interface
|
||||
// v6 address for the sandbox side pipe interface
|
||||
if config.EnableIPv6 {
|
||||
ip6, err := ipAllocator.RequestIP(n.bridge.bridgeIPv6, nil)
|
||||
if err != nil {
|
||||
|
@ -454,6 +475,24 @@ func (d *driver) DeleteEndpoint(nid, eid types.UUID) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func parseEndpointOptions(epOptions interface{}) (*EndpointConfiguration, error) {
|
||||
if epOptions == nil {
|
||||
return nil, nil
|
||||
}
|
||||
switch opt := epOptions.(type) {
|
||||
case options.Generic:
|
||||
opaqueConfig, err := options.GenerateFromModel(opt, &EndpointConfiguration{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return opaqueConfig.(*EndpointConfiguration), nil
|
||||
case *EndpointConfiguration:
|
||||
return opt, nil
|
||||
default:
|
||||
return nil, ErrInvalidEndpointConfig
|
||||
}
|
||||
}
|
||||
|
||||
// Generates a name to be used for a virtual ethernet
|
||||
// interface. The name is constructed by 'veth' appended
|
||||
// by a randomly generated hex value. (example: veth0f60e2c)
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
|
@ -56,3 +58,36 @@ func TestCreateFullOptions(t *testing.T) {
|
|||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
}
|
||||
func TestCreateLinkWithOptions(t *testing.T) {
|
||||
defer netutils.SetupTestNetNS(t)()
|
||||
|
||||
_, d := New()
|
||||
|
||||
config := &Configuration{BridgeName: DefaultBridgeName}
|
||||
if err := d.Config(config); err != nil {
|
||||
t.Fatalf("Failed to setup driver config: %v", err)
|
||||
}
|
||||
|
||||
err := d.CreateNetwork("net1", "")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
mac := net.HardwareAddr([]byte{0x1e, 0x67, 0x66, 0x44, 0x55, 0x66})
|
||||
epConf := &EndpointConfiguration{MacAddress: mac}
|
||||
|
||||
sinfo, err := d.CreateEndpoint("net1", "ep", "s1", epConf)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a link: %s", err.Error())
|
||||
}
|
||||
|
||||
ifaceName := sinfo.Interfaces[0].SrcName
|
||||
veth, err := netlink.LinkByName(ifaceName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(mac, veth.Attrs().HardwareAddr) {
|
||||
t.Fatalf("Failed to parse and program endpoint configuration")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,9 @@ var (
|
|||
// ErrInvalidConfig error is returned when a network is created on a driver without valid config.
|
||||
ErrInvalidConfig = errors.New("trying to create a network on a driver without valid config")
|
||||
|
||||
// ErrInvalidEndpointConfig error is returned when a endpoint create is attempted with an invalid endpoint configuration.
|
||||
ErrInvalidEndpointConfig = errors.New("trying to create an endpoint with an invalid endpoint configuration")
|
||||
|
||||
// ErrNetworkExists error is returned when a network already exists and another network is created.
|
||||
ErrNetworkExists = errors.New("network already exists, bridge can only have one network")
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ func TestLinkCreate(t *testing.T) {
|
|||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
sinfo, err := d.CreateEndpoint("dummy", "", "sb1", "")
|
||||
sinfo, err := d.CreateEndpoint("dummy", "", "sb1", nil)
|
||||
if err != nil {
|
||||
if _, ok := err.(InvalidEndpointIDError); !ok {
|
||||
t.Fatalf("Failed with a wrong error :%s", err.Error())
|
||||
|
@ -34,7 +34,7 @@ func TestLinkCreate(t *testing.T) {
|
|||
t.Fatalf("Failed to detect invalid config")
|
||||
}
|
||||
|
||||
sinfo, err = d.CreateEndpoint("dummy", "ep", "", "")
|
||||
sinfo, err = d.CreateEndpoint("dummy", "ep", "", nil)
|
||||
if err != nil {
|
||||
if _, ok := err.(InvalidSandboxIDError); !ok {
|
||||
t.Fatalf("Failed with a wrong error :%s", err.Error())
|
||||
|
@ -43,17 +43,17 @@ func TestLinkCreate(t *testing.T) {
|
|||
t.Fatalf("Failed to detect invalid config")
|
||||
}
|
||||
|
||||
sinfo, err = d.CreateEndpoint("dummy", "ep", "cc", "")
|
||||
sinfo, err = d.CreateEndpoint("dummy", "ep", "cc", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a link: %s", err.Error())
|
||||
}
|
||||
|
||||
_, err = d.CreateEndpoint("dummy", "ep", "cc2", "")
|
||||
_, err = d.CreateEndpoint("dummy", "ep", "cc2", nil)
|
||||
if err == nil {
|
||||
t.Fatalf("Failed to detect duplicate endpoint id on same network")
|
||||
}
|
||||
|
||||
_, err = d.CreateEndpoint("dummy", "ep2", "cc", "")
|
||||
_, err = d.CreateEndpoint("dummy", "ep2", "cc", nil)
|
||||
if err == nil {
|
||||
t.Fatalf("Failed to detect addition of more than one endpoint to same sandbox")
|
||||
}
|
||||
|
@ -110,12 +110,12 @@ func TestLinkCreateTwo(t *testing.T) {
|
|||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
_, err = d.CreateEndpoint("dummy", "ep", "s1", "")
|
||||
_, err = d.CreateEndpoint("dummy", "ep", "s1", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a link: %s", err.Error())
|
||||
}
|
||||
|
||||
_, err = d.CreateEndpoint("dummy", "ep", "s1", "")
|
||||
_, err = d.CreateEndpoint("dummy", "ep", "s1", nil)
|
||||
if err != nil {
|
||||
if err != driverapi.ErrEndpointExists {
|
||||
t.Fatalf("Failed with a wrong error :%s", err.Error())
|
||||
|
@ -140,7 +140,7 @@ func TestLinkCreateNoEnableIPv6(t *testing.T) {
|
|||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
sinfo, err := d.CreateEndpoint("dummy", "ep", "sb2", "")
|
||||
sinfo, err := d.CreateEndpoint("dummy", "ep", "sb2", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a link: %s", err.Error())
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ func TestLinkDelete(t *testing.T) {
|
|||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
_, err = d.CreateEndpoint("dummy", "ep1", "s1", "")
|
||||
_, err = d.CreateEndpoint("dummy", "ep1", "s1", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a link: %s", err.Error())
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ func Testbridge(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ep, err := network.CreateEndpoint("testep", "sb1", "")
|
||||
ep, err := network.CreateEndpoint("testep", "sb1", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ func TestDeleteNetworkWithActiveEndpoints(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ep, err := network.CreateEndpoint("testep", "sb2", "")
|
||||
ep, err := network.CreateEndpoint("testep", "sb2", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -273,7 +273,7 @@ func TestUnknownEndpoint(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ep, err := network.CreateEndpoint("testep", "sb1", "")
|
||||
ep, err := network.CreateEndpoint("testep", "sb1", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ create network namespaces and allocate interfaces for containers to use.
|
|||
// For each new container: allocate IP and interfaces. The returned network
|
||||
// settings will be used for container infos (inspect and such), as well as
|
||||
// iptables rules for port publishing.
|
||||
ep, err := network.CreateEndpoint("Endpoint1", networkNamespace.Key(), "")
|
||||
ep, err := network.CreateEndpoint("Endpoint1", networkNamespace.Key(), nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue