|
@@ -1,60 +1,61 @@
|
|
|
-// Package libnetwork provides basic fonctionalities and extension points to
|
|
|
-// create network namespaces and allocate interfaces for containers to use.
|
|
|
-//
|
|
|
-// // Create a network for containers to join.
|
|
|
-// network, err := libnetwork.NewNetwork("simplebridge", &Options{})
|
|
|
-// if err != nil {
|
|
|
-// return err
|
|
|
-// }
|
|
|
-//
|
|
|
-// // For a new container: create network namespace (providing the path).
|
|
|
-// networkPath := "/var/lib/docker/.../4d23e"
|
|
|
-// networkNamespace, err := libnetwork.NewNetworkNamespace(networkPath)
|
|
|
-// if err != nil {
|
|
|
-// return err
|
|
|
-// }
|
|
|
-//
|
|
|
-// // 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.
|
|
|
-// interfaces, err := network.Link(containerID)
|
|
|
-// if err != nil {
|
|
|
-// return err
|
|
|
-// }
|
|
|
-//
|
|
|
-// // Add interfaces to the namespace.
|
|
|
-// for _, interface := range interfaces {
|
|
|
-// if err := networkNamespace.AddInterface(interface); err != nil {
|
|
|
-// return err
|
|
|
-// }
|
|
|
-// }
|
|
|
-//
|
|
|
-package libnetwork
|
|
|
+/*
|
|
|
+Package libnetwork provides basic fonctionalities and extension points to
|
|
|
+create network namespaces and allocate interfaces for containers to use.
|
|
|
+
|
|
|
+// Create a new controller instance
|
|
|
+controller := libnetwork.New()
|
|
|
+
|
|
|
+options := options.Generic{}
|
|
|
+// Create a network for containers to join.
|
|
|
+network, err := controller.NewNetwork("simplebridge", "network1", options)
|
|
|
+if err != nil {
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// For a new container: create a sandbox instance (providing a unique key).
|
|
|
+// For linux it is a filesystem path
|
|
|
+networkPath := "/var/lib/docker/.../4d23e"
|
|
|
+networkNamespace, err := sandbox.NewSandbox(networkPath)
|
|
|
+if err != nil {
|
|
|
+ return
|
|
|
+}
|
|
|
|
|
|
-// 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
|
|
|
+// 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.
|
|
|
+_, sinfo, err := network.CreateEndpoint("Endpoint1", networkNamespace.Key(), "")
|
|
|
+if err != nil {
|
|
|
+ return
|
|
|
+}
|
|
|
|
|
|
- // The name that will be assigned to the interface once moves inside a
|
|
|
- // network namespace.
|
|
|
- DstName string
|
|
|
+// Add interfaces to the namespace.
|
|
|
+for _, iface := range sinfo.Interfaces {
|
|
|
+ if err := networkNamespace.AddInterface(iface); err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- // IPv4 address for the interface.
|
|
|
- Address string
|
|
|
+// Set the gateway IP
|
|
|
+if err := networkNamespace.SetGateway(sinfo.Gateway); err != nil {
|
|
|
+ return
|
|
|
+}
|
|
|
+*/
|
|
|
+package libnetwork
|
|
|
|
|
|
- // IPv6 address for the interface.
|
|
|
- AddressIPv6 string
|
|
|
+import (
|
|
|
+ "fmt"
|
|
|
+ "sync"
|
|
|
|
|
|
- // IPv4 gateway for the interface.
|
|
|
- Gateway string
|
|
|
+ "github.com/docker/docker/pkg/common"
|
|
|
+ "github.com/docker/libnetwork/driverapi"
|
|
|
+)
|
|
|
|
|
|
- // IPv6 gateway for the interface.
|
|
|
- GatewayIPv6 string
|
|
|
+// NetworkController provides the interface for controller instance which manages
|
|
|
+// networks.
|
|
|
+type NetworkController interface {
|
|
|
+ // Create a new network. The options parameter carry driver specific options.
|
|
|
+ // Labels support will be added in the near future.
|
|
|
+ NewNetwork(networkType, name string, options interface{}) (Network, error)
|
|
|
}
|
|
|
|
|
|
// A Network represents a logical connectivity zone that containers may
|
|
@@ -64,42 +65,176 @@ type Network interface {
|
|
|
// A user chosen name for this network.
|
|
|
Name() string
|
|
|
|
|
|
+ // A system generated id for this network.
|
|
|
+ ID() string
|
|
|
+
|
|
|
// The type of network, which corresponds to its managing driver.
|
|
|
Type() string
|
|
|
|
|
|
- // Create a new link to this network symbolically identified by the
|
|
|
- // specified unique name.
|
|
|
- Link(name string) ([]*Interface, error)
|
|
|
+ // Create a new endpoint to this network symbolically identified by the
|
|
|
+ // specified unique name. The options parameter carry driver specific options.
|
|
|
+ // Labels support will be added in the near future.
|
|
|
+ CreateEndpoint(name string, sboxKey string, options interface{}) (Endpoint, *driverapi.SandboxInfo, error)
|
|
|
|
|
|
+ // Delete the network.
|
|
|
Delete() error
|
|
|
}
|
|
|
|
|
|
-// Namespace represents a network namespace, mounted on a specific Path. It
|
|
|
-// holds a list of Interface, and more can be added dynamically.
|
|
|
-type Namespace interface {
|
|
|
- // The path where the network namespace is mounted.
|
|
|
- Path() string
|
|
|
+// Endpoint represents a logical connection between a network and a sandbox.
|
|
|
+type Endpoint interface {
|
|
|
+ // Delete endpoint.
|
|
|
+ Delete() error
|
|
|
+}
|
|
|
+
|
|
|
+type endpoint struct {
|
|
|
+ name string
|
|
|
+ id driverapi.UUID
|
|
|
+ network *network
|
|
|
+ sandboxInfo *driverapi.SandboxInfo
|
|
|
+}
|
|
|
|
|
|
- // The collection of Interface previously added with the AddInterface
|
|
|
- // method. Note that this doesn't incude network interfaces added in any
|
|
|
- // other way (such as the default loopback interface existing in any newly
|
|
|
- // created network namespace).
|
|
|
- Interfaces() []*Interface
|
|
|
+type network struct {
|
|
|
+ ctrlr *controller
|
|
|
+ name string
|
|
|
+ networkType string
|
|
|
+ id driverapi.UUID
|
|
|
+ endpoints map[driverapi.UUID]*endpoint
|
|
|
+ sync.Mutex
|
|
|
+}
|
|
|
+
|
|
|
+type networkTable map[driverapi.UUID]*network
|
|
|
|
|
|
- // Add an existing Interface to this namespace. The operation will rename
|
|
|
- // from the Interface SrcName to DstName as it moves, and reconfigure the
|
|
|
- // interface according to the specified settings.
|
|
|
- AddInterface(*Interface) error
|
|
|
+type controller struct {
|
|
|
+ networks networkTable
|
|
|
+ drivers driverTable
|
|
|
+ sync.Mutex
|
|
|
+}
|
|
|
+
|
|
|
+// New creates a new instance of network controller.
|
|
|
+func New() NetworkController {
|
|
|
+ return &controller{networkTable{}, enumerateDrivers(), sync.Mutex{}}
|
|
|
}
|
|
|
|
|
|
// NewNetwork creates a new network of the specified networkType. The options
|
|
|
// are driver specific and modeled in a generic way.
|
|
|
-func NewNetwork(networkType, name string, options DriverParams) (Network, error) {
|
|
|
- return createNetwork(networkType, name, options)
|
|
|
+func (c *controller) NewNetwork(networkType, name string, options interface{}) (Network, error) {
|
|
|
+ network := &network{name: name, networkType: networkType}
|
|
|
+ network.id = driverapi.UUID(common.GenerateRandomID())
|
|
|
+ network.ctrlr = c
|
|
|
+
|
|
|
+ d, ok := c.drivers[networkType]
|
|
|
+ if !ok {
|
|
|
+ return nil, fmt.Errorf("unknown driver %q", networkType)
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := d.CreateNetwork(network.id, options); err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ c.Lock()
|
|
|
+ c.networks[network.id] = network
|
|
|
+ c.Unlock()
|
|
|
+
|
|
|
+ return network, nil
|
|
|
}
|
|
|
|
|
|
-// NewNetworkNamespace creates a new network namespace mounted on the specified
|
|
|
-// path.
|
|
|
-func NewNetworkNamespace(path string) (Namespace, error) {
|
|
|
- return createNetworkNamespace(path)
|
|
|
+func (n *network) Name() string {
|
|
|
+ return n.name
|
|
|
+}
|
|
|
+
|
|
|
+func (n *network) ID() string {
|
|
|
+ return string(n.id)
|
|
|
+}
|
|
|
+
|
|
|
+func (n *network) Type() string {
|
|
|
+ return n.networkType
|
|
|
+}
|
|
|
+
|
|
|
+func (n *network) Delete() error {
|
|
|
+ var err error
|
|
|
+
|
|
|
+ d, ok := n.ctrlr.drivers[n.networkType]
|
|
|
+ if !ok {
|
|
|
+ return fmt.Errorf("unknown driver %q", n.networkType)
|
|
|
+ }
|
|
|
+
|
|
|
+ n.ctrlr.Lock()
|
|
|
+ _, ok = n.ctrlr.networks[n.id]
|
|
|
+ if !ok {
|
|
|
+ n.ctrlr.Unlock()
|
|
|
+ return fmt.Errorf("unknown network %s id %s", n.name, n.id)
|
|
|
+ }
|
|
|
+
|
|
|
+ n.Lock()
|
|
|
+ numEps := len(n.endpoints)
|
|
|
+ n.Unlock()
|
|
|
+ if numEps != 0 {
|
|
|
+ n.ctrlr.Unlock()
|
|
|
+ return fmt.Errorf("network %s has active endpoints", n.id)
|
|
|
+ }
|
|
|
+
|
|
|
+ delete(n.ctrlr.networks, n.id)
|
|
|
+ n.ctrlr.Unlock()
|
|
|
+ defer func() {
|
|
|
+ if err != nil {
|
|
|
+ n.ctrlr.Lock()
|
|
|
+ n.ctrlr.networks[n.id] = n
|
|
|
+ n.ctrlr.Unlock()
|
|
|
+ }
|
|
|
+ }()
|
|
|
+
|
|
|
+ err = d.DeleteNetwork(n.id)
|
|
|
+ return err
|
|
|
+}
|
|
|
+
|
|
|
+func (n *network) CreateEndpoint(name string, sboxKey string, options interface{}) (Endpoint, *driverapi.SandboxInfo, error) {
|
|
|
+ ep := &endpoint{name: name}
|
|
|
+ ep.id = driverapi.UUID(common.GenerateRandomID())
|
|
|
+ ep.network = n
|
|
|
+
|
|
|
+ d, ok := n.ctrlr.drivers[n.networkType]
|
|
|
+ if !ok {
|
|
|
+ return nil, nil, fmt.Errorf("unknown driver %q", n.networkType)
|
|
|
+ }
|
|
|
+
|
|
|
+ sinfo, err := d.CreateEndpoint(n.id, ep.id, sboxKey, options)
|
|
|
+ if err != nil {
|
|
|
+ return nil, nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ ep.sandboxInfo = sinfo
|
|
|
+ n.Lock()
|
|
|
+ n.endpoints[ep.id] = ep
|
|
|
+ n.Unlock()
|
|
|
+ return ep, sinfo, nil
|
|
|
+}
|
|
|
+
|
|
|
+func (ep *endpoint) Delete() error {
|
|
|
+ var err error
|
|
|
+
|
|
|
+ d, ok := ep.network.ctrlr.drivers[ep.network.networkType]
|
|
|
+ if !ok {
|
|
|
+ return fmt.Errorf("unknown driver %q", ep.network.networkType)
|
|
|
+ }
|
|
|
+
|
|
|
+ n := ep.network
|
|
|
+ n.Lock()
|
|
|
+ _, ok = n.endpoints[ep.id]
|
|
|
+ if !ok {
|
|
|
+ n.Unlock()
|
|
|
+ return fmt.Errorf("unknown endpoint %s id %s", ep.name, ep.id)
|
|
|
+ }
|
|
|
+
|
|
|
+ delete(n.endpoints, ep.id)
|
|
|
+ n.Unlock()
|
|
|
+ defer func() {
|
|
|
+ if err != nil {
|
|
|
+ n.Lock()
|
|
|
+ n.endpoints[ep.id] = ep
|
|
|
+ n.Unlock()
|
|
|
+ }
|
|
|
+ }()
|
|
|
+
|
|
|
+ err = d.DeleteEndpoint(n.id, ep.id)
|
|
|
+ return err
|
|
|
}
|