|
@@ -74,9 +74,7 @@ type networkConfiguration struct {
|
|
|
|
|
|
// endpointConfiguration represents the user specified configuration for the sandbox endpoint
|
|
|
type endpointConfiguration struct {
|
|
|
- MacAddress net.HardwareAddr
|
|
|
- PortBindings []types.PortBinding
|
|
|
- ExposedPorts []types.TransportPort
|
|
|
+ MacAddress net.HardwareAddr
|
|
|
}
|
|
|
|
|
|
// containerConfiguration represents the user specified configuration for a container
|
|
@@ -85,6 +83,12 @@ type containerConfiguration struct {
|
|
|
ChildEndpoints []string
|
|
|
}
|
|
|
|
|
|
+// cnnectivityConfiguration represents the user specified configuration regarding the external connectivity
|
|
|
+type connectivityConfiguration struct {
|
|
|
+ PortBindings []types.PortBinding
|
|
|
+ ExposedPorts []types.TransportPort
|
|
|
+}
|
|
|
+
|
|
|
type bridgeEndpoint struct {
|
|
|
id string
|
|
|
srcName string
|
|
@@ -93,6 +97,7 @@ type bridgeEndpoint struct {
|
|
|
macAddress net.HardwareAddr
|
|
|
config *endpointConfiguration // User specified parameters
|
|
|
containerConfig *containerConfiguration
|
|
|
+ extConnConfig *connectivityConfiguration
|
|
|
portMapping []types.PortBinding // Operation port bindings
|
|
|
}
|
|
|
|
|
@@ -183,7 +188,7 @@ func (c *networkConfiguration) Conflicts(o *networkConfiguration) error {
|
|
|
return fmt.Errorf("same configuration")
|
|
|
}
|
|
|
|
|
|
- // Also empty, becasue only one network with empty name is allowed
|
|
|
+ // Also empty, because only one network with empty name is allowed
|
|
|
if c.BridgeName == o.BridgeName {
|
|
|
return fmt.Errorf("networks have same bridge name")
|
|
|
}
|
|
@@ -450,7 +455,7 @@ func parseNetworkGenericOptions(data interface{}) (*networkConfiguration, error)
|
|
|
|
|
|
func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error {
|
|
|
if len(ipamV4Data) > 1 || len(ipamV6Data) > 1 {
|
|
|
- return types.ForbiddenErrorf("bridge driver doesnt support multiple subnets")
|
|
|
+ return types.ForbiddenErrorf("bridge driver doesn't support multiple subnets")
|
|
|
}
|
|
|
|
|
|
if len(ipamV4Data) == 0 {
|
|
@@ -543,6 +548,9 @@ func (d *driver) getNetworks() []*bridgeNetwork {
|
|
|
|
|
|
// Create a new network using bridge plugin
|
|
|
func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
|
|
|
+ if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" {
|
|
|
+ return types.BadRequestErrorf("ipv4 pool is empty")
|
|
|
+ }
|
|
|
// Sanity checks
|
|
|
d.Lock()
|
|
|
if _, ok := d.networks[id]; ok {
|
|
@@ -581,7 +589,7 @@ func (d *driver) createNetwork(config *networkConfiguration) error {
|
|
|
nw.Unlock()
|
|
|
if err := nwConfig.Conflicts(config); err != nil {
|
|
|
return types.ForbiddenErrorf("cannot create network %s (%s): conflicts with network %s (%s): %s",
|
|
|
- nwConfig.BridgeName, config.ID, nw.id, nw.config.BridgeName, err.Error())
|
|
|
+ config.ID, config.BridgeName, nwConfig.ID, nwConfig.BridgeName, err.Error())
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -948,28 +956,19 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // Create the sandbox side pipe interface
|
|
|
+ // Store the sandbox side pipe interface parameters
|
|
|
endpoint.srcName = containerIfName
|
|
|
endpoint.macAddress = ifInfo.MacAddress()
|
|
|
endpoint.addr = ifInfo.Address()
|
|
|
endpoint.addrv6 = ifInfo.AddressIPv6()
|
|
|
|
|
|
- // Down the interface before configuring mac address.
|
|
|
- if err = netlink.LinkSetDown(sbox); err != nil {
|
|
|
- return fmt.Errorf("could not set link down for container interface %s: %v", containerIfName, err)
|
|
|
- }
|
|
|
-
|
|
|
- // Set the sbox's MAC. If specified, use the one configured by user, otherwise generate one based on IP.
|
|
|
+ // Set the sbox's MAC if not provided. If specified, use the one configured by user, otherwise generate one based on IP.
|
|
|
if endpoint.macAddress == nil {
|
|
|
endpoint.macAddress = electMacAddress(epConfig, endpoint.addr.IP)
|
|
|
- if err := ifInfo.SetMacAddress(endpoint.macAddress); err != nil {
|
|
|
+ if err = ifInfo.SetMacAddress(endpoint.macAddress); err != nil {
|
|
|
return err
|
|
|
}
|
|
|
}
|
|
|
- err = netlink.LinkSetHardwareAddr(sbox, endpoint.macAddress)
|
|
|
- if err != nil {
|
|
|
- return fmt.Errorf("could not set mac address for container interface %s: %v", containerIfName, err)
|
|
|
- }
|
|
|
|
|
|
// Up the host interface after finishing all netlink configuration
|
|
|
if err = netlink.LinkSetUp(host); err != nil {
|
|
@@ -996,17 +995,11 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
|
|
}
|
|
|
|
|
|
endpoint.addrv6 = &net.IPNet{IP: ip6, Mask: network.Mask}
|
|
|
- if err := ifInfo.SetIPAddress(endpoint.addrv6); err != nil {
|
|
|
+ if err = ifInfo.SetIPAddress(endpoint.addrv6); err != nil {
|
|
|
return err
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // Program any required port mapping and store them in the endpoint
|
|
|
- endpoint.portMapping, err = n.allocatePorts(epConfig, endpoint, config.DefaultBindingIP, d.config.EnableUserlandProxy)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
return nil
|
|
|
}
|
|
|
|
|
@@ -1061,9 +1054,6 @@ func (d *driver) DeleteEndpoint(nid, eid string) error {
|
|
|
}
|
|
|
}()
|
|
|
|
|
|
- // Remove port mappings. Do not stop endpoint delete on unmap failure
|
|
|
- n.releasePorts(ep)
|
|
|
-
|
|
|
// Try removal of link. Discard error: it is a best effort.
|
|
|
// Also make sure defer does not see this error either.
|
|
|
if link, err := netlink.LinkByName(ep.srcName); err == nil {
|
|
@@ -1104,10 +1094,10 @@ func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, erro
|
|
|
|
|
|
m := make(map[string]interface{})
|
|
|
|
|
|
- if ep.config.ExposedPorts != nil {
|
|
|
+ if ep.extConnConfig != nil && ep.extConnConfig.ExposedPorts != nil {
|
|
|
// Return a copy of the config data
|
|
|
- epc := make([]types.TransportPort, 0, len(ep.config.ExposedPorts))
|
|
|
- for _, tp := range ep.config.ExposedPorts {
|
|
|
+ epc := make([]types.TransportPort, 0, len(ep.extConnConfig.ExposedPorts))
|
|
|
+ for _, tp := range ep.extConnConfig.ExposedPorts {
|
|
|
epc = append(epc, tp.GetCopy())
|
|
|
}
|
|
|
m[netlabel.ExposedPorts] = epc
|
|
@@ -1147,6 +1137,11 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
|
|
|
return EndpointNotFoundError(eid)
|
|
|
}
|
|
|
|
|
|
+ endpoint.containerConfig, err = parseContainerOptions(options)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
iNames := jinfo.InterfaceName()
|
|
|
err = iNames.SetNames(endpoint.srcName, containerVethPrefix)
|
|
|
if err != nil {
|
|
@@ -1163,10 +1158,6 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
- if !network.config.EnableICC {
|
|
|
- return d.link(network, endpoint, options, true)
|
|
|
- }
|
|
|
-
|
|
|
return nil
|
|
|
}
|
|
|
|
|
@@ -1189,32 +1180,87 @@ func (d *driver) Leave(nid, eid string) error {
|
|
|
}
|
|
|
|
|
|
if !network.config.EnableICC {
|
|
|
- return d.link(network, endpoint, nil, false)
|
|
|
+ if err = d.link(network, endpoint, false); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
-func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, options map[string]interface{}, enable bool) error {
|
|
|
- var (
|
|
|
- cc *containerConfiguration
|
|
|
- err error
|
|
|
- )
|
|
|
+func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
|
|
+ defer osl.InitOSContext()()
|
|
|
|
|
|
- if enable {
|
|
|
- cc, err = parseContainerOptions(options)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- } else {
|
|
|
- cc = endpoint.containerConfig
|
|
|
+ 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)
|
|
|
+ }
|
|
|
+
|
|
|
+ endpoint.extConnConfig, err = parseConnectivityOptions(options)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ // Program any required port mapping and store them in the endpoint
|
|
|
+ endpoint.portMapping, err = network.allocatePorts(endpoint, network.config.DefaultBindingIP, d.config.EnableUserlandProxy)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ if !network.config.EnableICC {
|
|
|
+ return d.link(network, endpoint, true)
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
|
|
+ defer osl.InitOSContext()()
|
|
|
+
|
|
|
+ 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)
|
|
|
+ }
|
|
|
+
|
|
|
+ err = network.releasePorts(endpoint)
|
|
|
+ if err != nil {
|
|
|
+ logrus.Warn(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, enable bool) error {
|
|
|
+ var err error
|
|
|
+
|
|
|
+ cc := endpoint.containerConfig
|
|
|
if cc == nil {
|
|
|
return nil
|
|
|
}
|
|
|
+ ec := endpoint.extConnConfig
|
|
|
+ if ec == nil {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
|
|
|
- if endpoint.config != nil && endpoint.config.ExposedPorts != nil {
|
|
|
+ if ec.ExposedPorts != nil {
|
|
|
for _, p := range cc.ParentEndpoints {
|
|
|
var parentEndpoint *bridgeEndpoint
|
|
|
parentEndpoint, err = network.getEndpoint(p)
|
|
@@ -1228,7 +1274,7 @@ func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, options
|
|
|
|
|
|
l := newLink(parentEndpoint.addr.IP.String(),
|
|
|
endpoint.addr.IP.String(),
|
|
|
- endpoint.config.ExposedPorts, network.config.BridgeName)
|
|
|
+ ec.ExposedPorts, network.config.BridgeName)
|
|
|
if enable {
|
|
|
err = l.Enable()
|
|
|
if err != nil {
|
|
@@ -1255,13 +1301,13 @@ func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, options
|
|
|
err = InvalidEndpointIDError(c)
|
|
|
return err
|
|
|
}
|
|
|
- if childEndpoint.config == nil || childEndpoint.config.ExposedPorts == nil {
|
|
|
+ if childEndpoint.extConnConfig == nil || childEndpoint.extConnConfig.ExposedPorts == nil {
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
l := newLink(endpoint.addr.IP.String(),
|
|
|
childEndpoint.addr.IP.String(),
|
|
|
- childEndpoint.config.ExposedPorts, network.config.BridgeName)
|
|
|
+ childEndpoint.extConnConfig.ExposedPorts, network.config.BridgeName)
|
|
|
if enable {
|
|
|
err = l.Enable()
|
|
|
if err != nil {
|
|
@@ -1277,10 +1323,6 @@ func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, options
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if enable {
|
|
|
- endpoint.containerConfig = cc
|
|
|
- }
|
|
|
-
|
|
|
return nil
|
|
|
}
|
|
|
|
|
@@ -1313,22 +1355,6 @@ func parseEndpointOptions(epOptions map[string]interface{}) (*endpointConfigurat
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if opt, ok := epOptions[netlabel.PortMap]; ok {
|
|
|
- if bs, ok := opt.([]types.PortBinding); ok {
|
|
|
- ec.PortBindings = bs
|
|
|
- } else {
|
|
|
- return nil, &ErrInvalidEndpointConfig{}
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if opt, ok := epOptions[netlabel.ExposedPorts]; ok {
|
|
|
- if ports, ok := opt.([]types.TransportPort); ok {
|
|
|
- ec.ExposedPorts = ports
|
|
|
- } else {
|
|
|
- return nil, &ErrInvalidEndpointConfig{}
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
return ec, nil
|
|
|
}
|
|
|
|
|
@@ -1354,6 +1380,32 @@ func parseContainerOptions(cOptions map[string]interface{}) (*containerConfigura
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+func parseConnectivityOptions(cOptions map[string]interface{}) (*connectivityConfiguration, error) {
|
|
|
+ if cOptions == nil {
|
|
|
+ return nil, nil
|
|
|
+ }
|
|
|
+
|
|
|
+ cc := &connectivityConfiguration{}
|
|
|
+
|
|
|
+ if opt, ok := cOptions[netlabel.PortMap]; ok {
|
|
|
+ if pb, ok := opt.([]types.PortBinding); ok {
|
|
|
+ cc.PortBindings = pb
|
|
|
+ } else {
|
|
|
+ return nil, types.BadRequestErrorf("Invalid port mapping data in connectivity configuration: %v", opt)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if opt, ok := cOptions[netlabel.ExposedPorts]; ok {
|
|
|
+ if ports, ok := opt.([]types.TransportPort); ok {
|
|
|
+ cc.ExposedPorts = ports
|
|
|
+ } else {
|
|
|
+ return nil, types.BadRequestErrorf("Invalid exposed ports data in connectivity configuration: %v", opt)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return cc, nil
|
|
|
+}
|
|
|
+
|
|
|
func electMacAddress(epConfig *endpointConfiguration, ip net.IP) net.HardwareAddr {
|
|
|
if epConfig != nil && epConfig.MacAddress != nil {
|
|
|
return epConfig.MacAddress
|