Join / Leave Driver API

Signed-off-by: Madhu Venugopal <madhu@docker.com>
This commit is contained in:
Madhu Venugopal 2015-04-30 14:52:46 -07:00
parent cc4f27f6af
commit 9db6a1b8e4
6 changed files with 109 additions and 10 deletions

View file

@ -40,6 +40,12 @@ type Driver interface {
// passing the network id and endpoint id.
DeleteEndpoint(nid, eid types.UUID) error
// Join method is invoked when a Sandbox is attached to an endpoint.
Join(nid, eid types.UUID, sboxKey string, options map[string]interface{}) error
// Leave method is invoked when a Sandbox detaches from an endpoint.
Leave(nid, eid types.UUID, options map[string]interface{}) error
// Type returns the the type of this driver, the network type this driver manages
Type() string
}

View file

@ -49,6 +49,11 @@ type EndpointConfiguration struct {
MacAddress net.HardwareAddr
}
// ContainerConfiguration represents the user specified configuration for a container
type ContainerConfiguration struct {
// TODO : Add container specific configuration when Join processing is handled
}
type bridgeEndpoint struct {
id types.UUID
port *sandbox.Interface
@ -175,7 +180,7 @@ func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) err
d.Lock()
if d.config == nil {
d.Unlock()
return ErrInvalidConfig
return ErrInvalidNetworkConfig
}
config := d.config
@ -554,6 +559,16 @@ func (d *driver) DeleteEndpoint(nid, eid types.UUID) error {
return 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{}) 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 {
return nil
}
func (d *driver) Type() string {
return networkType
}
@ -580,6 +595,24 @@ func parseEndpointOptions(epOptions map[string]interface{}) (*EndpointConfigurat
}
}
func parseContainerOptions(cOptions interface{}) (*ContainerConfiguration, error) {
if cOptions == nil {
return nil, nil
}
switch opt := cOptions.(type) {
case options.Generic:
opaqueConfig, err := options.GenerateFromModel(opt, &ContainerConfiguration{})
if err != nil {
return nil, err
}
return opaqueConfig.(*ContainerConfiguration), nil
case *ContainerConfiguration:
return opt, nil
default:
return nil, ErrInvalidContainerConfig
}
}
// 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)

View file

@ -13,8 +13,11 @@ var (
// ErrInvalidDriverConfig error is returned when Bridge Driver is passed an invalid config
ErrInvalidDriverConfig = errors.New("Invalid configuration passed to Bridge Driver")
// 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")
// ErrInvalidNetworkConfig error is returned when a network is created on a driver without valid config.
ErrInvalidNetworkConfig = errors.New("trying to create a network on a driver without valid config")
// ErrInvalidContainerConfig error is returned when a endpoint create is attempted with an invalid configuration.
ErrInvalidContainerConfig = errors.New("Error in joining a container due to invalid configuration")
// 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")

View file

@ -35,6 +35,16 @@ func (d *driver) DeleteEndpoint(nid, eid types.UUID) error {
return 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{}) 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 {
return nil
}
func (d *driver) Type() string {
return networkType
}

View file

@ -5,7 +5,6 @@ import (
"path/filepath"
"github.com/docker/docker/pkg/etchosts"
"github.com/docker/libnetwork/pkg/options"
"github.com/docker/libnetwork/sandbox"
"github.com/docker/libnetwork/types"
)
@ -28,7 +27,7 @@ type Endpoint interface {
// Leave removes the sandbox associated with container ID and detaches
// the network resources populated in the sandbox
Leave(containerID string) error
Leave(containerID string, options ...LeaveOption) error
// SandboxInfo returns the sandbox information for this endpoint.
SandboxInfo() *sandbox.Info
@ -48,9 +47,15 @@ type ContainerData struct {
// provided by libnetwork, they look like JoinOption[...](...)
type JoinOption func(ep *endpoint)
// LeaveOption is a option setter function type used to pass varios options to
// endpoint Leave method. The various setter functions of type LeaveOption are
// provided by libnetwork, they look like LeaveOptionXXXX(...)
type LeaveOption func(ep *endpoint)
type containerConfig struct {
Hostname string
Domainname string
generic map[string]interface{}
}
type containerInfo struct {
@ -66,7 +71,8 @@ type endpoint struct {
sandboxInfo *sandbox.Info
sandBox sandbox.Sandbox
container *containerInfo
generic options.Generic
generic map[string]interface{}
context map[string]interface{}
}
const prefix = "/var/lib/docker/network/files"
@ -179,6 +185,12 @@ func (ep *endpoint) Join(containerID string, options ...JoinOption) (*ContainerD
}
}()
n := ep.network
err = n.driver.Join(n.id, ep.id, sboxKey, ep.container.Config.generic)
if err != nil {
return nil, err
}
sinfo := ep.SandboxInfo()
if sinfo != nil {
for _, i := range sinfo.Interfaces {
@ -206,14 +218,23 @@ func (ep *endpoint) Join(containerID string, options ...JoinOption) (*ContainerD
return &cData, nil
}
func (ep *endpoint) Leave(containerID string) error {
func (ep *endpoint) Leave(containerID string, options ...LeaveOption) error {
if ep.container == nil || ep.container.ID == "" ||
containerID == "" || ep.container.ID != containerID {
return InvalidContainerIDError(containerID)
}
ep.network.ctrlr.sandboxRm(sandbox.GenerateKey(containerID))
n := ep.network
ep.processLeaveOptions(options...)
err := n.driver.Leave(n.id, ep.id, ep.context)
if err != nil {
return err
}
ep.network.ctrlr.sandboxRm(ep.container.Data.SandboxKey)
ep.container = nil
ep.context = nil
return nil
}
@ -276,6 +297,15 @@ func JoinOptionDomainname(name string) JoinOption {
}
}
// JoinOptionGeneric function returns an option setter for Generic configuration
// that is not managed by libNetwork but can be used by the Drivers during the call to
// endpoint join method. Container Labels are a good example.
func JoinOptionGeneric(generic map[string]interface{}) JoinOption {
return func(ep *endpoint) {
ep.container.Config.generic = generic
}
}
func (ep *endpoint) processJoinOptions(options ...JoinOption) {
for _, opt := range options {
if opt != nil {
@ -283,3 +313,20 @@ func (ep *endpoint) processJoinOptions(options ...JoinOption) {
}
}
}
// LeaveOptionGeneric function returns an option setter for Generic configuration
// that is not managed by libNetwork but can be used by the Drivers during the call to
// endpoint leave method. Container Labels are a good example.
func LeaveOptionGeneric(context map[string]interface{}) JoinOption {
return func(ep *endpoint) {
ep.context = context
}
}
func (ep *endpoint) processLeaveOptions(options ...LeaveOption) {
for _, opt := range options {
if opt != nil {
opt(ep)
}
}
}

View file

@ -173,12 +173,12 @@ func TestDuplicateNetwork(t *testing.T) {
err := controller.ConfigureNetworkDriver(netType, genericOption)
if err != nil {
t.Fatal(err.Error())
t.Fatal(err)
}
_, err = controller.NewNetwork(netType, "testnetwork", nil)
if err != nil {
t.Fatal("Expected to fail. But instead succeeded")
t.Fatal(err)
}
_, err = controller.NewNetwork(netType, "testnetwork")