diff --git a/libnetwork/.gitignore b/libnetwork/.gitignore index ce7eb7209d..b5f76babbc 100644 --- a/libnetwork/.gitignore +++ b/libnetwork/.gitignore @@ -26,3 +26,6 @@ _testmain.go # Coverage *.tmp *.coverprofile + +# IDE files +.project diff --git a/libnetwork/driverapi/driverapi.go b/libnetwork/driverapi/driverapi.go index b93d6a32c9..4e2ca06ab5 100644 --- a/libnetwork/driverapi/driverapi.go +++ b/libnetwork/driverapi/driverapi.go @@ -2,9 +2,9 @@ package driverapi import ( "errors" - "net" - "github.com/docker/libnetwork/netutils" + "github.com/docker/libnetwork/sandbox" + "github.com/docker/libnetwork/types" ) var ( @@ -16,9 +16,6 @@ var ( ErrNoEndpoint = errors.New("No endpoint exists") ) -// UUID represents a globally unique ID of various resources like network and endpoint -type UUID string - // Driver is an interface that every plugin driver needs to implement. type Driver interface { // Push driver specific config to the driver @@ -27,136 +24,19 @@ type Driver interface { // CreateNetwork invokes the driver method to create a network passing // the network id and network specific config. The config mechanism will // eventually be replaced with labels which are yet to be introduced. - CreateNetwork(nid UUID, config interface{}) error + CreateNetwork(nid types.UUID, config interface{}) error // DeleteNetwork invokes the driver method to delete network passing // the network id. - DeleteNetwork(nid UUID) error + DeleteNetwork(nid types.UUID) error // CreateEndpoint invokes the driver method to create an endpoint // passing the network id, endpoint id, sandbox key and driver // specific config. The config mechanism will eventually be replaced // with labels which are yet to be introduced. - CreateEndpoint(nid, eid UUID, key string, config interface{}) (*SandboxInfo, error) + CreateEndpoint(nid, eid types.UUID, key string, config interface{}) (*sandbox.Info, error) // DeleteEndpoint invokes the driver method to delete an endpoint // passing the network id and endpoint id. - DeleteEndpoint(nid, eid UUID) error -} - -// Interface represents the settings and identity of a network device. It is -// used as a return type for Network.Link, and it is common practice for the -// caller to use this information when moving interface SrcName from host -// namespace to DstName in a different net namespace with the appropriate -// network settings. -type Interface struct { - // The name of the interface in the origin network namespace. - SrcName string - - // The name that will be assigned to the interface once moves inside a - // network namespace. - DstName string - - // IPv4 address for the interface. - Address *net.IPNet - - // IPv6 address for the interface. - AddressIPv6 *net.IPNet -} - -// SandboxInfo represents all possible information that -// the driver wants to place in the sandbox which includes -// interfaces, routes and gateway -type SandboxInfo struct { - Interfaces []*Interface - - // IPv4 gateway for the sandbox. - Gateway net.IP - - // IPv6 gateway for the sandbox. - GatewayIPv6 net.IP - - // TODO: Add routes and ip tables etc. -} - -// GetCopy returns a copy of this Interface structure -func (i *Interface) GetCopy() *Interface { - return &Interface{ - SrcName: i.SrcName, - DstName: i.DstName, - Address: netutils.GetIPNetCopy(i.Address), - AddressIPv6: netutils.GetIPNetCopy(i.AddressIPv6), - } -} - -// Equal checks if this instance of Interface is equal to the passed one -func (i *Interface) Equal(o *Interface) bool { - if i == o { - return true - } - - if o == nil { - return false - } - - if i.SrcName != o.SrcName || i.DstName != o.DstName { - return false - } - - if !netutils.CompareIPNet(i.Address, o.Address) { - return false - } - - if !netutils.CompareIPNet(i.AddressIPv6, o.AddressIPv6) { - return false - } - - return true -} - -// GetCopy returns a copy of this SandboxInfo structure -func (s *SandboxInfo) GetCopy() *SandboxInfo { - list := make([]*Interface, len(s.Interfaces)) - for i, iface := range s.Interfaces { - list[i] = iface.GetCopy() - } - gw := netutils.GetIPCopy(s.Gateway) - gw6 := netutils.GetIPCopy(s.GatewayIPv6) - - return &SandboxInfo{Interfaces: list, Gateway: gw, GatewayIPv6: gw6} -} - -// Equal checks if this instance of SandboxInfo is equal to the passed one -func (s *SandboxInfo) Equal(o *SandboxInfo) bool { - if s == o { - return true - } - - if o == nil { - return false - } - - if !s.Gateway.Equal(o.Gateway) { - return false - } - - if !s.GatewayIPv6.Equal(o.GatewayIPv6) { - return false - } - - if (s.Interfaces == nil && o.Interfaces != nil) || - (s.Interfaces != nil && o.Interfaces == nil) || - (len(s.Interfaces) != len(o.Interfaces)) { - return false - } - - // Note: At the moment, the two lists must be in the same order - for i := 0; i < len(s.Interfaces); i++ { - if !s.Interfaces[i].Equal(o.Interfaces[i]) { - return false - } - } - - return true - + DeleteEndpoint(nid, eid types.UUID) error } diff --git a/libnetwork/driverapi/driverapi_test.go b/libnetwork/driverapi/driverapi_test.go deleted file mode 100644 index e9f7089f53..0000000000 --- a/libnetwork/driverapi/driverapi_test.go +++ /dev/null @@ -1,71 +0,0 @@ -package driverapi - -import ( - "net" - "testing" -) - -func TestInterfaceEqual(t *testing.T) { - list := getInterfaceList() - - if !list[0].Equal(list[0]) { - t.Fatalf("Interface.Equal() returned false negative") - } - - if list[0].Equal(list[1]) { - t.Fatalf("Interface.Equal() returned false positive") - } - - if list[0].Equal(list[1]) != list[1].Equal(list[0]) { - t.Fatalf("Interface.Equal() failed commutative check") - } -} - -func TestInterfaceCopy(t *testing.T) { - for _, iface := range getInterfaceList() { - cp := iface.GetCopy() - - if !iface.Equal(cp) { - t.Fatalf("Failed to return a copy of Interface") - } - - if iface == cp { - t.Fatalf("Failed to return a true copy of Interface") - } - } -} - -func TestSandboxInfoCopy(t *testing.T) { - si := SandboxInfo{Interfaces: getInterfaceList(), Gateway: net.ParseIP("192.168.1.254"), GatewayIPv6: net.ParseIP("2001:2345::abcd:8889")} - cp := si.GetCopy() - - if !si.Equal(cp) { - t.Fatalf("Failed to return a copy of SandboxInfo") - } - - if &si == cp { - t.Fatalf("Failed to return a true copy of SanboxInfo") - } -} - -func getInterfaceList() []*Interface { - _, netv4a, _ := net.ParseCIDR("192.168.30.1/24") - _, netv4b, _ := net.ParseCIDR("172.18.255.2/23") - _, netv6a, _ := net.ParseCIDR("2001:2345::abcd:8888/80") - _, netv6b, _ := net.ParseCIDR("2001:2345::abcd:8889/80") - - return []*Interface{ - &Interface{ - SrcName: "veth1234567", - DstName: "eth0", - Address: netv4a, - AddressIPv6: netv6a, - }, - &Interface{ - SrcName: "veth7654321", - DstName: "eth1", - Address: netv4b, - AddressIPv6: netv6b, - }, - } -} diff --git a/libnetwork/drivers/bridge/bridge.go b/libnetwork/drivers/bridge/bridge.go index 92e58bb59c..6e3d3a773c 100644 --- a/libnetwork/drivers/bridge/bridge.go +++ b/libnetwork/drivers/bridge/bridge.go @@ -10,6 +10,8 @@ import ( "github.com/docker/libnetwork/netutils" "github.com/docker/libnetwork/pkg/options" "github.com/docker/libnetwork/portmapper" + "github.com/docker/libnetwork/sandbox" + "github.com/docker/libnetwork/types" "github.com/vishvananda/netlink" ) @@ -40,13 +42,13 @@ type Configuration struct { } type bridgeEndpoint struct { - id driverapi.UUID + id types.UUID addressIPv4 net.IP addressIPv6 net.IP } type bridgeNetwork struct { - id driverapi.UUID + id types.UUID // bridge interface points to the linux bridge and it's configuration bridge *bridgeInterface endpoint *bridgeEndpoint @@ -95,7 +97,7 @@ func (d *driver) Config(option interface{}) error { } // Create a new network using simplebridge plugin -func (d *driver) CreateNetwork(id driverapi.UUID, option interface{}) error { +func (d *driver) CreateNetwork(id types.UUID, option interface{}) error { var ( err error @@ -178,7 +180,7 @@ func (d *driver) CreateNetwork(id driverapi.UUID, option interface{}) error { return nil } -func (d *driver) DeleteNetwork(nid driverapi.UUID) error { +func (d *driver) DeleteNetwork(nid types.UUID) error { var err error d.Lock() n := d.network @@ -211,7 +213,7 @@ func (d *driver) DeleteNetwork(nid driverapi.UUID) error { return err } -func (d *driver) CreateEndpoint(nid, eid driverapi.UUID, sboxKey string, epOption interface{}) (*driverapi.SandboxInfo, error) { +func (d *driver) CreateEndpoint(nid, eid types.UUID, sboxKey string, epOption interface{}) (*sandbox.Info, error) { var ( ipv6Addr *net.IPNet ip6 net.IP @@ -303,10 +305,10 @@ func (d *driver) CreateEndpoint(nid, eid driverapi.UUID, sboxKey string, epOptio ipv6Addr = &net.IPNet{IP: ip6, Mask: n.bridge.bridgeIPv6.Mask} } - var interfaces []*driverapi.Interface - sinfo := &driverapi.SandboxInfo{} + var interfaces []*sandbox.Interface + sinfo := &sandbox.Info{} - intf := &driverapi.Interface{} + intf := &sandbox.Interface{} intf.SrcName = name2 intf.DstName = containerVeth intf.Address = ipv4Addr @@ -323,7 +325,7 @@ func (d *driver) CreateEndpoint(nid, eid driverapi.UUID, sboxKey string, epOptio return sinfo, nil } -func (d *driver) DeleteEndpoint(nid, eid driverapi.UUID) error { +func (d *driver) DeleteEndpoint(nid, eid types.UUID) error { var err error d.Lock() diff --git a/libnetwork/network.go b/libnetwork/network.go index c0eb49d73e..9fccfc3657 100644 --- a/libnetwork/network.go +++ b/libnetwork/network.go @@ -43,6 +43,8 @@ import ( "github.com/docker/docker/pkg/stringid" "github.com/docker/libnetwork/driverapi" + "github.com/docker/libnetwork/sandbox" + "github.com/docker/libnetwork/types" ) // NetworkController provides the interface for controller instance which manages @@ -91,7 +93,7 @@ type Endpoint interface { Network() string // SandboxInfo returns the sandbox information for this endpoint. - SandboxInfo() *driverapi.SandboxInfo + SandboxInfo() *sandbox.Info // Delete and detaches this endpoint from the network. Delete() error @@ -105,23 +107,23 @@ type NetworkDriver struct { type endpoint struct { name string - id driverapi.UUID + id types.UUID network *network - sandboxInfo *driverapi.SandboxInfo + sandboxInfo *sandbox.Info } type network struct { ctrlr *controller name string networkType string - id driverapi.UUID + id types.UUID driver *NetworkDriver endpoints endpointTable sync.Mutex } -type networkTable map[driverapi.UUID]*network -type endpointTable map[driverapi.UUID]*endpoint +type networkTable map[types.UUID]*network +type endpointTable map[types.UUID]*endpoint type controller struct { networks networkTable @@ -165,7 +167,7 @@ func (c *controller) NewNetwork(nd *NetworkDriver, name string, options interfac network := &network{ name: name, - id: driverapi.UUID(stringid.GenerateRandomID()), + id: types.UUID(stringid.GenerateRandomID()), ctrlr: c, driver: nd} network.endpoints = make(endpointTable) @@ -237,7 +239,7 @@ func (n *network) Delete() error { func (n *network) CreateEndpoint(name string, sboxKey string, options interface{}) (Endpoint, error) { ep := &endpoint{name: name} - ep.id = driverapi.UUID(stringid.GenerateRandomID()) + ep.id = types.UUID(stringid.GenerateRandomID()) ep.network = n d := n.driver.internalDriver @@ -280,7 +282,7 @@ func (ep *endpoint) Network() string { return ep.network.name } -func (ep *endpoint) SandboxInfo() *driverapi.SandboxInfo { +func (ep *endpoint) SandboxInfo() *sandbox.Info { if ep.sandboxInfo == nil { return nil } diff --git a/libnetwork/sandbox/configure_linux.go b/libnetwork/sandbox/configure_linux.go index 066954f74e..761e016ef4 100644 --- a/libnetwork/sandbox/configure_linux.go +++ b/libnetwork/sandbox/configure_linux.go @@ -4,14 +4,13 @@ import ( "fmt" "net" - "github.com/docker/libnetwork/driverapi" "github.com/vishvananda/netlink" ) -func configureInterface(iface netlink.Link, settings *driverapi.Interface) error { +func configureInterface(iface netlink.Link, settings *Interface) error { ifaceName := iface.Attrs().Name ifaceConfigurators := []struct { - Fn func(netlink.Link, *driverapi.Interface) error + Fn func(netlink.Link, *Interface) error ErrMessage string }{ {setInterfaceName, fmt.Sprintf("error renaming interface %q to %q", ifaceName, settings.DstName)}, @@ -34,16 +33,16 @@ func setGatewayIP(gw net.IP) error { }) } -func setInterfaceIP(iface netlink.Link, settings *driverapi.Interface) error { +func setInterfaceIP(iface netlink.Link, settings *Interface) error { ipAddr := &netlink.Addr{IPNet: settings.Address, Label: ""} return netlink.AddrAdd(iface, ipAddr) } -func setInterfaceIPv6(iface netlink.Link, settings *driverapi.Interface) error { +func setInterfaceIPv6(iface netlink.Link, settings *Interface) error { ipAddr := &netlink.Addr{IPNet: settings.Address, Label: ""} return netlink.AddrAdd(iface, ipAddr) } -func setInterfaceName(iface netlink.Link, settings *driverapi.Interface) error { +func setInterfaceName(iface netlink.Link, settings *Interface) error { return netlink.LinkSetName(iface, settings.DstName) } diff --git a/libnetwork/sandbox/namespace_linux.go b/libnetwork/sandbox/namespace_linux.go index 47972d0856..47d5204a5d 100644 --- a/libnetwork/sandbox/namespace_linux.go +++ b/libnetwork/sandbox/namespace_linux.go @@ -7,7 +7,6 @@ import ( "runtime" "syscall" - "github.com/docker/libnetwork/driverapi" "github.com/vishvananda/netlink" "github.com/vishvananda/netns" ) @@ -17,7 +16,7 @@ import ( // into it when called on method AddInterface or sets the gateway etc. type networkNamespace struct { path string - sinfo *driverapi.SandboxInfo + sinfo *Info } // NewSandbox provides a new sandbox instance created in an os specific way @@ -74,7 +73,7 @@ func loopbackUp() error { return netlink.LinkSetUp(iface) } -func (n *networkNamespace) AddInterface(i *driverapi.Interface) error { +func (n *networkNamespace) AddInterface(i *Interface) error { runtime.LockOSThread() defer runtime.UnlockOSThread() @@ -139,7 +138,7 @@ func (n *networkNamespace) SetGatewayIPv6(gw net.IP) error { return err } -func (n *networkNamespace) Interfaces() []*driverapi.Interface { +func (n *networkNamespace) Interfaces() []*Interface { return n.sinfo.Interfaces } diff --git a/libnetwork/sandbox/sandbox.go b/libnetwork/sandbox/sandbox.go index 6c9c93af4c..45405e08a4 100644 --- a/libnetwork/sandbox/sandbox.go +++ b/libnetwork/sandbox/sandbox.go @@ -3,7 +3,7 @@ package sandbox import ( "net" - "github.com/docker/libnetwork/driverapi" + "github.com/docker/libnetwork/netutils" ) // Sandbox represents a network sandbox, identified by a specific key. It @@ -16,12 +16,12 @@ type Sandbox interface { // method. Note that this doesn't incude network interfaces added in any // other way (such as the default loopback interface which are automatically // created on creation of a sandbox). - Interfaces() []*driverapi.Interface + Interfaces() []*Interface // Add an existing Interface to this sandbox. The operation will rename // from the Interface SrcName to DstName as it moves, and reconfigure the // interface according to the specified settings. - AddInterface(*driverapi.Interface) error + AddInterface(*Interface) error // Set default IPv4 gateway for the sandbox SetGateway(gw net.IP) error @@ -29,3 +29,120 @@ type Sandbox interface { // Set default IPv6 gateway for the sandbox SetGatewayIPv6(gw net.IP) error } + +// Info represents all possible information that +// the driver wants to place in the sandbox which includes +// interfaces, routes and gateway +type Info struct { + Interfaces []*Interface + + // IPv4 gateway for the sandbox. + Gateway net.IP + + // IPv6 gateway for the sandbox. + GatewayIPv6 net.IP + + // TODO: Add routes and ip tables etc. +} + +// Interface represents the settings and identity of a network device. It is +// used as a return type for Network.Link, and it is common practice for the +// caller to use this information when moving interface SrcName from host +// namespace to DstName in a different net namespace with the appropriate +// network settings. +type Interface struct { + // The name of the interface in the origin network namespace. + SrcName string + + // The name that will be assigned to the interface once moves inside a + // network namespace. + DstName string + + // IPv4 address for the interface. + Address *net.IPNet + + // IPv6 address for the interface. + AddressIPv6 *net.IPNet +} + +// GetCopy returns a copy of this Interface structure +func (i *Interface) GetCopy() *Interface { + return &Interface{ + SrcName: i.SrcName, + DstName: i.DstName, + Address: netutils.GetIPNetCopy(i.Address), + AddressIPv6: netutils.GetIPNetCopy(i.AddressIPv6), + } +} + +// Equal checks if this instance of Interface is equal to the passed one +func (i *Interface) Equal(o *Interface) bool { + if i == o { + return true + } + + if o == nil { + return false + } + + if i.SrcName != o.SrcName || i.DstName != o.DstName { + return false + } + + if !netutils.CompareIPNet(i.Address, o.Address) { + return false + } + + if !netutils.CompareIPNet(i.AddressIPv6, o.AddressIPv6) { + return false + } + + return true +} + +// GetCopy returns a copy of this SandboxInfo structure +func (s *Info) GetCopy() *Info { + list := make([]*Interface, len(s.Interfaces)) + for i, iface := range s.Interfaces { + list[i] = iface.GetCopy() + } + gw := netutils.GetIPCopy(s.Gateway) + gw6 := netutils.GetIPCopy(s.GatewayIPv6) + + return &Info{Interfaces: list, Gateway: gw, GatewayIPv6: gw6} +} + +// Equal checks if this instance of SandboxInfo is equal to the passed one +func (s *Info) Equal(o *Info) bool { + if s == o { + return true + } + + if o == nil { + return false + } + + if !s.Gateway.Equal(o.Gateway) { + return false + } + + if !s.GatewayIPv6.Equal(o.GatewayIPv6) { + return false + } + + if (s.Interfaces == nil && o.Interfaces != nil) || + (s.Interfaces != nil && o.Interfaces == nil) || + (len(s.Interfaces) != len(o.Interfaces)) { + return false + } + + // Note: At the moment, the two lists must be in the same order + for i := 0; i < len(s.Interfaces); i++ { + if !s.Interfaces[i].Equal(o.Interfaces[i]) { + return false + } + } + + return true + +} diff --git a/libnetwork/sandbox/sandbox_test.go b/libnetwork/sandbox/sandbox_test.go index 07ea68dc1b..2678466d58 100644 --- a/libnetwork/sandbox/sandbox_test.go +++ b/libnetwork/sandbox/sandbox_test.go @@ -1,6 +1,9 @@ package sandbox -import "testing" +import ( + "net" + "testing" +) func TestSandboxCreate(t *testing.T) { key, err := newKey(t) @@ -19,3 +22,68 @@ func TestSandboxCreate(t *testing.T) { verifySandbox(t, s) } + +func TestInterfaceEqual(t *testing.T) { + list := getInterfaceList() + + if !list[0].Equal(list[0]) { + t.Fatalf("Interface.Equal() returned false negative") + } + + if list[0].Equal(list[1]) { + t.Fatalf("Interface.Equal() returned false positive") + } + + if list[0].Equal(list[1]) != list[1].Equal(list[0]) { + t.Fatalf("Interface.Equal() failed commutative check") + } +} + +func TestInterfaceCopy(t *testing.T) { + for _, iface := range getInterfaceList() { + cp := iface.GetCopy() + + if !iface.Equal(cp) { + t.Fatalf("Failed to return a copy of Interface") + } + + if iface == cp { + t.Fatalf("Failed to return a true copy of Interface") + } + } +} + +func TestSandboxInfoCopy(t *testing.T) { + si := Info{Interfaces: getInterfaceList(), Gateway: net.ParseIP("192.168.1.254"), GatewayIPv6: net.ParseIP("2001:2345::abcd:8889")} + cp := si.GetCopy() + + if !si.Equal(cp) { + t.Fatalf("Failed to return a copy of Info") + } + + if &si == cp { + t.Fatalf("Failed to return a true copy of Info") + } +} + +func getInterfaceList() []*Interface { + _, netv4a, _ := net.ParseCIDR("192.168.30.1/24") + _, netv4b, _ := net.ParseCIDR("172.18.255.2/23") + _, netv6a, _ := net.ParseCIDR("2001:2345::abcd:8888/80") + _, netv6b, _ := net.ParseCIDR("2001:2345::abcd:8889/80") + + return []*Interface{ + &Interface{ + SrcName: "veth1234567", + DstName: "eth0", + Address: netv4a, + AddressIPv6: netv6a, + }, + &Interface{ + SrcName: "veth7654321", + DstName: "eth1", + Address: netv4b, + AddressIPv6: netv6b, + }, + } +} diff --git a/libnetwork/types/types.go b/libnetwork/types/types.go new file mode 100644 index 0000000000..363d4ab73c --- /dev/null +++ b/libnetwork/types/types.go @@ -0,0 +1,5 @@ +// Package types contains types that are common across libnetwork project +package types + +// UUID represents a globally unique ID of various resources like network and endpoint +type UUID string