Exemple #1
0
// Checks whether this network's configuration for the network with this id conflicts with any of the passed networks
func (c *networkConfiguration) conflictsWithNetworks(id types.UUID, others []*bridgeNetwork) error {
	for _, nw := range others {

		nw.Lock()
		nwID := nw.id
		nwConfig := nw.config
		nwBridge := nw.bridge
		nw.Unlock()

		if nwID == id {
			continue
		}
		// Verify the name (which may have been set by newInterface()) does not conflict with
		// existing bridge interfaces. Ironically the system chosen name gets stored in the config...
		// Basically we are checking if the two original configs were both empty.
		if nwConfig.BridgeName == c.BridgeName {
			return types.ForbiddenErrorf("conflicts with network %s (%s) by bridge name", nwID, nwConfig.BridgeName)
		}
		// If this network config specifies the AddressIPv4, we need
		// to make sure it does not conflict with any previously allocated
		// bridges. This could not be completely caught by the config conflict
		// check, because networks which config does not specify the AddressIPv4
		// get their address and subnet selected by the driver (see electBridgeIPv4())
		if c.AddressIPv4 != nil {
			if nwBridge.bridgeIPv4.Contains(c.AddressIPv4.IP) ||
				c.AddressIPv4.Contains(nwBridge.bridgeIPv4.IP) {
				return types.ForbiddenErrorf("conflicts with network %s (%s) by ip network", nwID, nwConfig.BridgeName)
			}
		}
	}

	return nil
}
func (ep *endpoint) Leave(sbox Sandbox, options ...EndpointOption) error {
	ep.joinLeaveStart()
	defer ep.joinLeaveEnd()

	if sbox == nil || sbox.ID() == "" || sbox.Key() == "" {
		return types.BadRequestErrorf("invalid Sandbox passed to enpoint leave: %v", sbox)
	}

	sb, ok := sbox.(*sandbox)
	if !ok {
		return types.BadRequestErrorf("not a valid Sandbox interface")
	}

	ep.Lock()
	sid := ep.sandboxID
	ep.Unlock()

	if sid == "" {
		return types.ForbiddenErrorf("cannot leave endpoint with no attached sandbox")
	}
	if sid != sbox.ID() {
		return types.ForbiddenErrorf("unexpected sandbox ID in leave request. Expected %s. Got %s", ep.sandboxID, sbox.ID())
	}

	ep.processOptions(options...)

	ep.Lock()
	ep.sandboxID = ""
	n := ep.network
	ep.Unlock()

	n.Lock()
	c := n.ctrlr
	d := n.driver
	n.Unlock()

	if err := c.updateEndpointToStore(ep); err != nil {
		ep.Lock()
		ep.sandboxID = sid
		ep.Unlock()
		return err
	}

	if err := d.Leave(n.id, ep.id); err != nil {
		return err
	}

	if err := sb.clearNetworkResources(ep); err != nil {
		return err
	}

	if sb.needDefaultGW() {
		ep := sb.getEPwithoutGateway()
		if ep == nil {
			return fmt.Errorf("endpoint without GW expected, but not found")
		}
		return sb.setupDefaultGW(ep)
	}
	return sb.clearDefaultGW()
}
Exemple #3
0
func (a *Allocator) initializeAddressSpace(as string, ds datastore.DataStore) error {
	scope := ""
	if ds != nil {
		scope = ds.Scope()
	}

	a.Lock()
	if currAS, ok := a.addrSpaces[as]; ok {
		if currAS.ds != nil {
			a.Unlock()
			return types.ForbiddenErrorf("a datastore is already configured for the address space %s", as)
		}
	}
	a.addrSpaces[as] = &addrSpace{
		subnets: map[SubnetKey]*PoolData{},
		id:      dsConfigKey + "/" + as,
		scope:   scope,
		ds:      ds,
		alloc:   a,
	}
	a.Unlock()

	a.checkConsistency(as)

	return nil
}
Exemple #4
0
func setAddress(ifaceAddr *string, address *net.IPNet) error {
	if *ifaceAddr != "" {
		return types.ForbiddenErrorf("endpoint interface IP present (%s). Cannot be modified with (%s).", *ifaceAddr, address)
	}
	*ifaceAddr = address.String()
	return nil
}
Exemple #5
0
func (r *DrvRegistry) registerIpamDriver(name string, driver ipamapi.Ipam, caps *ipamapi.Capability) error {
	if strings.TrimSpace(name) == "" {
		return fmt.Errorf("ipam driver name string cannot be empty")
	}

	r.Lock()
	_, ok := r.ipamDrivers[name]
	r.Unlock()
	if ok {
		return types.ForbiddenErrorf("ipam driver %q already registered", name)
	}

	locAS, glbAS, err := driver.GetDefaultAddressSpaces()
	if err != nil {
		return types.InternalErrorf("ipam driver %q failed to return default address spaces: %v", name, err)
	}

	if r.ifn != nil {
		if err := r.ifn(name, driver, caps); err != nil {
			return err
		}
	}

	r.Lock()
	r.ipamDrivers[name] = &ipamData{driver: driver, defaultLocalAddressSpace: locAS, defaultGlobalAddressSpace: glbAS, capability: caps}
	r.Unlock()

	return nil
}
Exemple #6
0
func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error {
	if len(ipamV4Data) > 1 || len(ipamV6Data) > 1 {
		return types.ForbiddenErrorf("bridge driver doesn't support multiple subnets")
	}

	if len(ipamV4Data) == 0 {
		return types.BadRequestErrorf("bridge network %s requires ipv4 configuration", id)
	}

	if ipamV4Data[0].Gateway != nil {
		c.AddressIPv4 = types.GetIPNetCopy(ipamV4Data[0].Gateway)
	}

	if gw, ok := ipamV4Data[0].AuxAddresses[DefaultGatewayV4AuxKey]; ok {
		c.DefaultGatewayIPv4 = gw.IP
	}

	if len(ipamV6Data) > 0 {
		c.AddressIPv6 = ipamV6Data[0].Pool

		if ipamV6Data[0].Gateway != nil {
			c.AddressIPv6 = types.GetIPNetCopy(ipamV6Data[0].Gateway)
		}

		if gw, ok := ipamV6Data[0].AuxAddresses[DefaultGatewayV6AuxKey]; ok {
			c.DefaultGatewayIPv6 = gw.IP
		}
	}

	return nil
}
Exemple #7
0
// 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 {
		d.Unlock()
		return types.ForbiddenErrorf("network %s exists", id)
	}
	d.Unlock()

	// Parse and validate the config. It should not conflict with existing networks' config
	config, err := parseNetworkOptions(id, option)
	if err != nil {
		return err
	}

	err = config.processIPAM(id, ipV4Data, ipV6Data)
	if err != nil {
		return err
	}

	if err = d.createNetwork(config); err != nil {
		return err
	}

	return d.storeUpdate(config)
}
Exemple #8
0
func setAddress(ifaceAddr **net.IPNet, address *net.IPNet) error {
	if *ifaceAddr != nil {
		return types.ForbiddenErrorf("endpoint interface IP present (%s). Cannot be modified with (%s).", *ifaceAddr, address)
	}
	*ifaceAddr = types.GetIPNetCopy(address)
	return nil
}
Exemple #9
0
func (sb *sandbox) SetKey(basePath string) error {
	var err error
	if basePath == "" {
		return types.BadRequestErrorf("invalid sandbox key")
	}

	sb.Lock()
	if sb.osSbox != nil {
		sb.Unlock()
		return types.ForbiddenErrorf("failed to set sandbox key : already assigned")
	}
	sb.Unlock()
	osSbox, err := osl.GetSandboxForExternalKey(basePath, sb.Key())
	if err != nil {
		return err
	}
	sb.Lock()
	sb.osSbox = osSbox
	sb.Unlock()
	defer func() {
		if err != nil {
			sb.Lock()
			sb.osSbox = nil
			sb.Unlock()
		}
	}()

	for _, ep := range sb.getConnectedEndpoints() {
		if err = sb.populateNetworkResources(ep); err != nil {
			return err
		}
	}
	return nil
}
Exemple #10
0
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
	switch dType {
	case discoverapi.NodeDiscovery:
		nodeData, ok := data.(discoverapi.NodeDiscoveryData)
		if !ok || nodeData.Address == "" {
			return fmt.Errorf("invalid discovery data")
		}
		d.nodeJoin(nodeData.Address, nodeData.Self)
	case discoverapi.DatastoreConfig:
		var err error
		if d.store != nil {
			return types.ForbiddenErrorf("cannot accept datastore configuration: Overlay driver has a datastore configured already")
		}
		dsc, ok := data.(discoverapi.DatastoreConfigData)
		if !ok {
			return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
		}
		d.store, err = datastore.NewDataStoreFromConfig(dsc)
		if err != nil {
			return types.InternalErrorf("failed to initialize data store: %v", err)
		}
	default:
	}
	return nil
}
Exemple #11
0
func (d *driver) setKeys(keys []*key) error {
	if d.keys != nil {
		return types.ForbiddenErrorf("initial keys are already present")
	}
	d.keys = keys
	logrus.Debugf("Initial encryption keys: %v", d.keys)
	return nil
}
Exemple #12
0
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
	var err error
	switch dType {
	case discoverapi.NodeDiscovery:
		nodeData, ok := data.(discoverapi.NodeDiscoveryData)
		if !ok || nodeData.Address == "" {
			return fmt.Errorf("invalid discovery data")
		}
		d.nodeJoin(nodeData.Address, nodeData.Self)
	case discoverapi.DatastoreConfig:
		if d.store != nil {
			return types.ForbiddenErrorf("cannot accept datastore configuration: Overlay driver has a datastore configured already")
		}
		dsc, ok := data.(discoverapi.DatastoreConfigData)
		if !ok {
			return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
		}
		d.store, err = datastore.NewDataStoreFromConfig(dsc)
		if err != nil {
			return types.InternalErrorf("failed to initialize data store: %v", err)
		}
	case discoverapi.EncryptionKeysConfig:
		encrData, ok := data.(discoverapi.DriverEncryptionConfig)
		if !ok {
			return fmt.Errorf("invalid encryption key notification data")
		}
		keys := make([]*key, 0, len(encrData.Keys))
		for i := 0; i < len(encrData.Keys); i++ {
			k, err := parseEncryptionKey(encrData.Keys[i], encrData.Tags[i])
			if err != nil {
				return err
			}
			keys = append(keys, k)
		}
		d.setKeys(keys)
	case discoverapi.EncryptionKeysUpdate:
		var newKey, delKey, priKey *key
		encrData, ok := data.(discoverapi.DriverEncryptionUpdate)
		if !ok {
			return fmt.Errorf("invalid encryption key notification data")
		}
		newKey, err = parseEncryptionKey(encrData.Key, encrData.Tag)
		if err != nil {
			return err
		}
		priKey, err = parseEncryptionKey(encrData.Primary, encrData.PrimaryTag)
		if err != nil {
			return err
		}
		delKey, err = parseEncryptionKey(encrData.Prune, encrData.PruneTag)
		if err != nil {
			return err
		}
		d.updateKeys(newKey, priKey, delKey)
	default:
	}
	return nil
}
Exemple #13
0
func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoint, error) {
	var err error
	if !config.IsValidName(name) {
		return nil, ErrInvalidName(name)
	}

	if _, err = n.EndpointByName(name); err == nil {
		return nil, types.ForbiddenErrorf("service endpoint with name %s already exists", name)
	}

	ep := &endpoint{name: name, generic: make(map[string]interface{}), iface: &endpointInterface{}}
	ep.id = stringid.GenerateRandomID()
	ep.network = n
	ep.processOptions(options...)

	if err = ep.assignAddress(); err != nil {
		return nil, err
	}
	defer func() {
		if err != nil {
			ep.releaseAddress()
		}
	}()

	ctrlr := n.getController()

	n.IncEndpointCnt()
	if err = ctrlr.updateToStore(n); err != nil {
		return nil, err
	}
	defer func() {
		if err != nil {
			n.DecEndpointCnt()
			if err = ctrlr.updateToStore(n); err != nil {
				log.Warnf("endpoint count cleanup failed when updating network for %s : %v", name, err)
			}
		}
	}()
	if err = n.addEndpoint(ep); err != nil {
		return nil, err
	}
	defer func() {
		if err != nil {
			if e := ep.Delete(); ep != nil {
				log.Warnf("cleaning up endpoint failed %s : %v", name, e)
			}
		}
	}()

	if !ep.isLocalScoped() {
		if err = ctrlr.updateToStore(ep); err != nil {
			return nil, err
		}
	}

	return ep, nil
}
Exemple #14
0
func (i *testInterface) SetMacAddress(mac net.HardwareAddr) error {
	if i.mac != nil {
		return types.ForbiddenErrorf("endpoint interface MAC address present (%s). Cannot be modified with %s.", i.mac, mac)
	}
	if mac == nil {
		return types.BadRequestErrorf("tried to set nil MAC address to endpoint interface")
	}
	i.mac = types.GetMacCopy(mac)
	return nil
}
Exemple #15
0
func (test *testEndpoint) SetMacAddress(mac net.HardwareAddr) error {
	if test.macAddress != "" {
		return types.ForbiddenErrorf("endpoint interface MAC address present (%s). Cannot be modified with %s.", test.macAddress, mac)
	}
	if mac == nil {
		return types.BadRequestErrorf("tried to set nil MAC address to endpoint interface")
	}
	test.macAddress = mac.String()
	return nil
}
Exemple #16
0
func (sb *sandbox) Delete() error {
	sb.Lock()
	if sb.inDelete {
		sb.Unlock()
		return types.ForbiddenErrorf("another sandbox delete in progress")
	}
	// Set the inDelete flag. This will ensure that we don't
	// update the store until we have completed all the endpoint
	// leaves and deletes. And when endpoint leaves and deletes
	// are completed then we can finally delete the sandbox object
	// altogether from the data store. If the daemon exits
	// ungracefully in the middle of a sandbox delete this way we
	// will have all the references to the endpoints in the
	// sandbox so that we can clean them up when we restart
	sb.inDelete = true
	sb.Unlock()

	c := sb.controller

	// Detach from all endpoints
	for _, ep := range sb.getConnectedEndpoints() {
		// endpoint in the Gateway network will be cleaned up
		// when when sandbox no longer needs external connectivity
		if ep.endpointInGWNetwork() {
			continue
		}

		if err := ep.Leave(sb); err != nil {
			log.Warnf("Failed detaching sandbox %s from endpoint %s: %v\n", sb.ID(), ep.ID(), err)
		}

		if err := ep.Delete(); err != nil {
			log.Warnf("Failed deleting endpoint %s: %v\n", ep.ID(), err)
		}
	}

	// Container is going away. Path cache in etchosts is most
	// likely not required any more. Drop it.
	etchosts.Drop(sb.config.hostsPath)

	if sb.osSbox != nil {
		sb.osSbox.Destroy()
	}

	if err := sb.storeDelete(); err != nil {
		log.Warnf("Failed to delete sandbox %s from store: %v", sb.ID(), err)
	}

	c.Lock()
	delete(c.sandboxes, sb.ID())
	c.Unlock()

	return nil
}
Exemple #17
0
func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error {
	if len(ipamV6Data) > 0 {
		return types.ForbiddenErrorf("windowsshim driver doesnt support v6 subnets")
	}

	if len(ipamV4Data) == 0 {
		return types.BadRequestErrorf("network %s requires ipv4 configuration", id)
	}

	return nil
}
func (epi *endpointInterface) SetIPAliases(aliases []*net.IPNet) error {

	if epi.ipAliases != nil {
		return types.ForbiddenErrorf("endpoint aliases present. Cannot be modified with (%s).", aliases)
	}
	epi.ipAliases = make([]*net.IPNet, 0)
	for _, alias := range aliases {
		epi.ipAliases = append(epi.ipAliases, types.GetIPNetCopy(alias))
	}
	return nil
}
Exemple #19
0
func (d *driver) CreateNetwork(id string, option map[string]interface{}) error {
	d.Lock()
	defer d.Unlock()

	if d.network != "" {
		return types.ForbiddenErrorf("only one instance of \"%s\" network is allowed", networkType)
	}

	d.network = id

	return nil
}
Exemple #20
0
func (ep *endpoint) SetIPAddress(address *net.IPNet) error {
	if address.IP == nil {
		return types.BadRequestErrorf("tried to set nil IP address to endpoint interface")
	}
	if address.IP.To4() == nil {
		return types.NotImplementedErrorf("do not support ipv6 yet")
	}
	if ep.addr != nil {
		return types.ForbiddenErrorf("endpoint interface IP present (%s). Cannot be modified with %s.", ep.addr, address)
	}
	ep.addr = types.GetIPNetCopy(address)
	return nil
}
Exemple #21
0
func (d *driver) checkEncryption(nid string, rIP net.IP, vxlanID uint32, isLocal, add bool) error {
	logrus.Debugf("checkEncryption(%s, %v, %d, %t)", nid[0:7], rIP, vxlanID, isLocal)

	n := d.network(nid)
	if n == nil || !n.secure {
		return nil
	}

	if len(d.keys) == 0 {
		return types.ForbiddenErrorf("encryption key is not present")
	}

	lIP := net.ParseIP(d.bindAddress)
	aIP := net.ParseIP(d.advertiseAddress)
	nodes := map[string]net.IP{}

	switch {
	case isLocal:
		if err := d.peerDbNetworkWalk(nid, func(pKey *peerKey, pEntry *peerEntry) bool {
			if !aIP.Equal(pEntry.vtep) {
				nodes[pEntry.vtep.String()] = pEntry.vtep
			}
			return false
		}); err != nil {
			logrus.Warnf("Failed to retrieve list of participating nodes in overlay network %s: %v", nid[0:5], err)
		}
	default:
		if len(d.network(nid).endpoints) > 0 {
			nodes[rIP.String()] = rIP
		}
	}

	logrus.Debugf("List of nodes: %s", nodes)

	if add {
		for _, rIP := range nodes {
			if err := setupEncryption(lIP, aIP, rIP, vxlanID, d.secMap, d.keys); err != nil {
				logrus.Warnf("Failed to program network encryption between %s and %s: %v", lIP, rIP, err)
			}
		}
	} else {
		if len(nodes) == 0 {
			if err := removeEncryption(lIP, rIP, d.secMap); err != nil {
				logrus.Warnf("Failed to remove network encryption between %s and %s: %v", lIP, rIP, err)
			}
		}
	}

	return nil
}
Exemple #22
0
func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoint, error) {
	var err error
	if !config.IsValidName(name) {
		return nil, ErrInvalidName(name)
	}

	if _, err = n.EndpointByName(name); err == nil {
		return nil, types.ForbiddenErrorf("service endpoint with name %s already exists", name)
	}

	ep := &endpoint{name: name,
		iFaces:  []*endpointInterface{},
		generic: make(map[string]interface{})}
	ep.id = types.UUID(stringid.GenerateRandomID())
	ep.network = n
	ep.processOptions(options...)

	n.Lock()
	ctrlr := n.ctrlr
	n.Unlock()

	n.IncEndpointCnt()
	if err = ctrlr.updateNetworkToStore(n); err != nil {
		return nil, err
	}
	defer func() {
		if err != nil {
			n.DecEndpointCnt()
			if err = ctrlr.updateNetworkToStore(n); err != nil {
				log.Warnf("endpoint count cleanup failed when updating network for %s : %v", name, err)
			}
		}
	}()
	if err = n.addEndpoint(ep); err != nil {
		return nil, err
	}
	defer func() {
		if err != nil {
			if e := ep.Delete(); ep != nil {
				log.Warnf("cleaning up endpoint failed %s : %v", name, e)
			}
		}
	}()

	if err = ctrlr.updateEndpointToStore(ep); err != nil {
		return nil, err
	}

	return ep, nil
}
Exemple #23
0
func (a *Allocator) initializeAddressSpace(as string, ds datastore.DataStore) error {
	a.Lock()
	if _, ok := a.addrSpaces[as]; ok {
		a.Unlock()
		return types.ForbiddenErrorf("tried to add an axisting address space: %s", as)
	}
	a.addrSpaces[as] = &addrSpace{
		subnets: map[SubnetKey]*PoolData{},
		id:      dsConfigKey + "/" + as,
		scope:   ds.Scope(),
		ds:      ds,
		alloc:   a,
	}
	a.Unlock()

	a.checkConsistency(as)

	return nil
}
Exemple #24
0
func (c *networkConfig) parseIPAM(id string, ipamV4Data, ipamV6Data []*driverapi.IPAMData) error {
	if len(ipamV4Data) > 1 || len(ipamV6Data) > 1 {
		return types.ForbiddenErrorf("bridge driver doesni't support multiple subnets")
	}

	if len(ipamV4Data) == 0 {
		return types.BadRequestErrorf("bridge network %s requires ipv4 configuration", id)
	}

	if ipamV4Data[0].Gateway == "" {
		return types.BadRequestErrorf("bridge network %s requires ipv4 gateway from IPAM", id)
	}
	if gw, _, err := net.ParseCIDR(ipamV4Data[0].Gateway); err != nil {
		return err
	} else {
		Log.Debugf("IPAM: %v", *ipamV4Data[0])
		c.GatewayIPv4 = gw
	}

	return nil
}
Exemple #25
0
func (c *controller) registerIpamDriver(name string, driver ipamapi.Ipam, caps *ipamapi.Capability) error {
	if !config.IsValidName(name) {
		return ErrInvalidName(name)
	}

	c.Lock()
	_, ok := c.ipamDrivers[name]
	c.Unlock()
	if ok {
		return types.ForbiddenErrorf("ipam driver %q already registered", name)
	}
	locAS, glbAS, err := driver.GetDefaultAddressSpaces()
	if err != nil {
		return types.InternalErrorf("ipam driver %q failed to return default address spaces: %v", name, err)
	}
	c.Lock()
	c.ipamDrivers[name] = &ipamData{driver: driver, defaultLocalAddressSpace: locAS, defaultGlobalAddressSpace: glbAS, capability: caps}
	c.Unlock()

	log.Debugf("Registering ipam driver: %q", name)

	return nil
}
Exemple #26
0
func (d *driver) DeleteNetwork(nid types.UUID) error {
	var err error

	defer sandbox.InitOSContext()()

	// Get network handler and remove it from driver
	d.Lock()
	n, ok := d.networks[nid]
	d.Unlock()

	if !ok {
		return types.InternalMaskableErrorf("network %s does not exist", nid)
	}

	n.Lock()
	config := n.config
	n.Unlock()

	if config.BridgeName == DefaultBridgeName {
		return types.ForbiddenErrorf("default network of type \"%s\" cannot be deleted", networkType)
	}

	d.Lock()
	delete(d.networks, nid)
	d.Unlock()

	// On failure set network handler back in driver, but
	// only if is not already taken over by some other thread
	defer func() {
		if err != nil {
			d.Lock()
			if _, ok := d.networks[nid]; !ok {
				d.networks[nid] = n
			}
			d.Unlock()
		}
	}()

	// Sanity check
	if n == nil {
		err = driverapi.ErrNoNetwork(nid)
		return err
	}

	// Cannot remove network if endpoints are still present
	if len(n.endpoints) != 0 {
		err = ActiveEndpointsError(n.id)
		return err
	}

	// In case of failures after this point, restore the network isolation rules
	nwList := d.getNetworks()
	defer func() {
		if err != nil {
			if err := n.isolateNetwork(nwList, true); err != nil {
				logrus.Warnf("Failed on restoring the inter-network iptables rules on cleanup: %v", err)
			}
		}
	}()

	// Remove inter-network communication rules.
	err = n.isolateNetwork(nwList, false)
	if err != nil {
		return err
	}

	// Programming
	err = netlink.LinkDel(n.bridge.Link)

	return err
}
Exemple #27
0
// Create a new network using bridge plugin
func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) error {
	var err error

	defer sandbox.InitOSContext()()

	// Sanity checks
	d.Lock()
	if _, ok := d.networks[id]; ok {
		d.Unlock()
		return types.ForbiddenErrorf("network %s exists", id)
	}
	d.Unlock()

	// Parse and validate the config. It should not conflict with existing networks' config
	config, err := parseNetworkOptions(option)
	if err != nil {
		return err
	}
	networkList := d.getNetworks()
	for _, nw := range networkList {
		nw.Lock()
		nwConfig := nw.config
		nw.Unlock()
		if nwConfig.Conflicts(config) {
			return types.ForbiddenErrorf("conflicts with network %s (%s)", nw.id, nw.config.BridgeName)
		}
	}

	// Create and set network handler in driver
	network := &bridgeNetwork{
		id:         id,
		endpoints:  make(map[types.UUID]*bridgeEndpoint),
		config:     config,
		portMapper: portmapper.New(),
	}

	d.Lock()
	d.networks[id] = network
	d.Unlock()

	// On failure make sure to reset driver network handler to nil
	defer func() {
		if err != nil {
			d.Lock()
			delete(d.networks, id)
			d.Unlock()
		}
	}()

	// Create or retrieve the bridge L3 interface
	bridgeIface := newInterface(config)
	network.bridge = bridgeIface

	// Verify the network configuration does not conflict with previously installed
	// networks. This step is needed now because driver might have now set the bridge
	// name on this config struct. And because we need to check for possible address
	// conflicts, so we need to check against operationa lnetworks.
	if err = config.conflictsWithNetworks(id, networkList); err != nil {
		return err
	}

	setupNetworkIsolationRules := func(config *networkConfiguration, i *bridgeInterface) error {
		if err := network.isolateNetwork(networkList, true); err != nil {
			if err := network.isolateNetwork(networkList, false); err != nil {
				logrus.Warnf("Failed on removing the inter-network iptables rules on cleanup: %v", err)
			}
			return err
		}
		return nil
	}

	// Prepare the bridge setup configuration
	bridgeSetup := newBridgeSetup(config, bridgeIface)

	// If the bridge interface doesn't exist, we need to start the setup steps
	// by creating a new device and assigning it an IPv4 address.
	bridgeAlreadyExists := bridgeIface.exists()
	if !bridgeAlreadyExists {
		bridgeSetup.queueStep(setupDevice)
	}

	// Even if a bridge exists try to setup IPv4.
	bridgeSetup.queueStep(setupBridgeIPv4)

	enableIPv6Forwarding := false
	if d.config != nil && d.config.EnableIPForwarding && config.FixedCIDRv6 != nil {
		enableIPv6Forwarding = true
	}

	// Conditionally queue setup steps depending on configuration values.
	for _, step := range []struct {
		Condition bool
		Fn        setupStep
	}{
		// Enable IPv6 on the bridge if required. We do this even for a
		// previously  existing bridge, as it may be here from a previous
		// installation where IPv6 wasn't supported yet and needs to be
		// assigned an IPv6 link-local address.
		{config.EnableIPv6, setupBridgeIPv6},

		// We ensure that the bridge has the expectedIPv4 and IPv6 addresses in
		// the case of a previously existing device.
		{bridgeAlreadyExists, setupVerifyAndReconcile},

		// Setup the bridge to allocate containers IPv4 addresses in the
		// specified subnet.
		{config.FixedCIDR != nil, setupFixedCIDRv4},

		// Setup the bridge to allocate containers global IPv6 addresses in the
		// specified subnet.
		{config.FixedCIDRv6 != nil, setupFixedCIDRv6},

		// Enable IPv6 Forwarding
		{enableIPv6Forwarding, setupIPv6Forwarding},

		// Setup Loopback Adresses Routing
		{!config.EnableUserlandProxy, setupLoopbackAdressesRouting},

		// Setup IPTables.
		{config.EnableIPTables, network.setupIPTables},

		//We want to track firewalld configuration so that
		//if it is started/reloaded, the rules can be applied correctly
		{config.EnableIPTables, network.setupFirewalld},

		// Setup DefaultGatewayIPv4
		{config.DefaultGatewayIPv4 != nil, setupGatewayIPv4},

		// Setup DefaultGatewayIPv6
		{config.DefaultGatewayIPv6 != nil, setupGatewayIPv6},

		// Add inter-network communication rules.
		{config.EnableIPTables, setupNetworkIsolationRules},

		//Configure bridge networking filtering if ICC is off and IP tables are enabled
		{!config.EnableICC && config.EnableIPTables, setupBridgeNetFiltering},
	} {
		if step.Condition {
			bridgeSetup.queueStep(step.Fn)
		}
	}

	// Block bridge IP from being allocated.
	bridgeSetup.queueStep(allocateBridgeIP)
	// Apply the prepared list of steps, and abort at the first error.
	bridgeSetup.queueStep(setupDeviceUp)
	if err = bridgeSetup.apply(); err != nil {
		return err
	}

	return nil
}
Exemple #28
0
// Create a new network
func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
	if _, err := d.getNetwork(id); err == nil {
		return types.ForbiddenErrorf("network %s exists", id)
	}

	genData, ok := option[netlabel.GenericData].(map[string]string)
	if !ok {
		return fmt.Errorf("Unknown generic data option")
	}

	// Parse and validate the config. It should not conflict with existing networks' config
	config, err := d.parseNetworkOptions(id, genData)
	if err != nil {
		return err
	}

	err = config.processIPAM(id, ipV4Data, ipV6Data)
	if err != nil {
		return err
	}

	network := &hnsNetwork{
		id:        config.ID,
		endpoints: make(map[string]*hnsEndpoint),
		config:    config,
		driver:    d,
	}

	d.Lock()
	d.networks[config.ID] = network
	d.Unlock()

	// A non blank hnsid indicates that the network was discovered
	// from HNS. No need to call HNS if this network was discovered
	// from HNS
	if config.HnsID == "" {
		subnets := []hcsshim.Subnet{}

		for _, ipData := range ipV4Data {
			subnet := hcsshim.Subnet{
				AddressPrefix:  ipData.Pool.String(),
				GatewayAddress: ipData.Gateway.IP.String(),
			}

			subnets = append(subnets, subnet)
		}

		network := &hcsshim.HNSNetwork{
			Name:    config.Name,
			Type:    d.name,
			Subnets: subnets,
		}

		if network.Name == "" {
			network.Name = id
		}

		configurationb, err := json.Marshal(network)
		if err != nil {
			return err
		}

		configuration := string(configurationb)
		log.Debugf("HNSNetwork Request =%v Address Space=%v", configuration, subnets)

		hnsresponse, err := hcsshim.HNSNetworkRequest("POST", "", configuration)
		if err != nil {
			return err
		}

		config.HnsID = hnsresponse.Id
		genData[HNSID] = config.HnsID
	}

	return nil
}
func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) error {
	n, err := ep.getNetworkFromStore()
	if err != nil {
		return fmt.Errorf("failed to get network from store during join: %v", err)
	}

	ep, err = n.getEndpointFromStore(ep.ID())
	if err != nil {
		return fmt.Errorf("failed to get endpoint from store during join: %v", err)
	}

	ep.Lock()
	if ep.sandboxID != "" {
		ep.Unlock()
		return types.ForbiddenErrorf("another container is attached to the same network endpoint")
	}
	ep.network = n
	ep.sandboxID = sb.ID()
	ep.joinInfo = &endpointJoinInfo{}
	epid := ep.id
	ep.Unlock()
	defer func() {
		if err != nil {
			ep.Lock()
			ep.sandboxID = ""
			ep.Unlock()
		}
	}()

	nid := n.ID()

	ep.processOptions(options...)

	d, err := n.driver(true)
	if err != nil {
		return fmt.Errorf("failed to join endpoint: %v", err)
	}

	err = d.Join(nid, epid, sb.Key(), ep, sb.Labels())
	if err != nil {
		return err
	}
	defer func() {
		if err != nil {
			if err := d.Leave(nid, epid); err != nil {
				log.Warnf("driver leave failed while rolling back join: %v", err)
			}
		}
	}()

	// Watch for service records
	if !n.getController().isAgent() {
		n.getController().watchSvcRecord(ep)
	}

	if doUpdateHostsFile(n, sb) {
		address := ""
		if ip := ep.getFirstInterfaceAddress(); ip != nil {
			address = ip.String()
		}
		if err = sb.updateHostsFile(address); err != nil {
			return err
		}
	}
	if err = sb.updateDNS(n.enableIPv6); err != nil {
		return err
	}

	if err = n.getController().updateToStore(ep); err != nil {
		return err
	}

	// Current endpoint providing external connectivity for the sandbox
	extEp := sb.getGatewayEndpoint()

	sb.Lock()
	heap.Push(&sb.endpoints, ep)
	sb.Unlock()
	defer func() {
		if err != nil {
			sb.removeEndpoint(ep)
		}
	}()

	if err = sb.populateNetworkResources(ep); err != nil {
		return err
	}

	if e := ep.addToCluster(); e != nil {
		log.Errorf("Could not update state for endpoint %s into cluster: %v", ep.Name(), e)
	}

	if sb.needDefaultGW() && sb.getEndpointInGWNetwork() == nil {
		return sb.setupDefaultGW()
	}

	moveExtConn := sb.getGatewayEndpoint() != extEp

	if moveExtConn {
		if extEp != nil {
			log.Debugf("Revoking external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
			extN, err := extEp.getNetworkFromStore()
			if err != nil {
				return fmt.Errorf("failed to get network from store during join: %v", err)
			}
			extD, err := extN.driver(true)
			if err != nil {
				return fmt.Errorf("failed to join endpoint: %v", err)
			}
			if err = extD.RevokeExternalConnectivity(extEp.network.ID(), extEp.ID()); err != nil {
				return types.InternalErrorf(
					"driver failed revoking external connectivity on endpoint %s (%s): %v",
					extEp.Name(), extEp.ID(), err)
			}
			defer func() {
				if err != nil {
					if e := extD.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); e != nil {
						log.Warnf("Failed to roll-back external connectivity on endpoint %s (%s): %v",
							extEp.Name(), extEp.ID(), e)
					}
				}
			}()
		}
		if !n.internal {
			log.Debugf("Programming external connectivity on endpoint %s (%s)", ep.Name(), ep.ID())
			if err = d.ProgramExternalConnectivity(n.ID(), ep.ID(), sb.Labels()); err != nil {
				return types.InternalErrorf(
					"driver failed programming external connectivity on endpoint %s (%s): %v",
					ep.Name(), ep.ID(), err)
			}
		}

	}

	if !sb.needDefaultGW() {
		if err := sb.clearDefaultGW(); err != nil {
			log.Warnf("Failure while disconnecting sandbox %s (%s) from gateway network: %v",
				sb.ID(), sb.ContainerID(), err)
		}
	}

	return nil
}
func (ep *endpoint) sbLeave(sb *sandbox, force bool, options ...EndpointOption) error {
	n, err := ep.getNetworkFromStore()
	if err != nil {
		return fmt.Errorf("failed to get network from store during leave: %v", err)
	}

	ep, err = n.getEndpointFromStore(ep.ID())
	if err != nil {
		return fmt.Errorf("failed to get endpoint from store during leave: %v", err)
	}

	ep.Lock()
	sid := ep.sandboxID
	ep.Unlock()

	if sid == "" {
		return types.ForbiddenErrorf("cannot leave endpoint with no attached sandbox")
	}
	if sid != sb.ID() {
		return types.ForbiddenErrorf("unexpected sandbox ID in leave request. Expected %s. Got %s", ep.sandboxID, sb.ID())
	}

	ep.processOptions(options...)

	d, err := n.driver(!force)
	if err != nil {
		return fmt.Errorf("failed to leave endpoint: %v", err)
	}

	ep.Lock()
	ep.sandboxID = ""
	ep.network = n
	ep.Unlock()

	// Current endpoint providing external connectivity to the sandbox
	extEp := sb.getGatewayEndpoint()
	moveExtConn := extEp != nil && (extEp.ID() == ep.ID())

	if d != nil {
		if moveExtConn {
			log.Debugf("Revoking external connectivity on endpoint %s (%s)", ep.Name(), ep.ID())
			if err := d.RevokeExternalConnectivity(n.id, ep.id); err != nil {
				log.Warnf("driver failed revoking external connectivity on endpoint %s (%s): %v",
					ep.Name(), ep.ID(), err)
			}
		}

		if err := d.Leave(n.id, ep.id); err != nil {
			if _, ok := err.(types.MaskableError); !ok {
				log.Warnf("driver error disconnecting container %s : %v", ep.name, err)
			}
		}
	}

	if err := sb.clearNetworkResources(ep); err != nil {
		log.Warnf("Could not cleanup network resources on container %s disconnect: %v", ep.name, err)
	}

	// Update the store about the sandbox detach only after we
	// have completed sb.clearNetworkresources above to avoid
	// spurious logs when cleaning up the sandbox when the daemon
	// ungracefully exits and restarts before completing sandbox
	// detach but after store has been updated.
	if err := n.getController().updateToStore(ep); err != nil {
		return err
	}

	if e := ep.deleteFromCluster(); e != nil {
		log.Errorf("Could not delete state for endpoint %s from cluster: %v", ep.Name(), e)
	}

	sb.deleteHostsEntries(n.getSvcRecords(ep))
	if !sb.inDelete && sb.needDefaultGW() && sb.getEndpointInGWNetwork() == nil {
		return sb.setupDefaultGW()
	}

	// New endpoint providing external connectivity for the sandbox
	extEp = sb.getGatewayEndpoint()
	if moveExtConn && extEp != nil {
		log.Debugf("Programming external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
		extN, err := extEp.getNetworkFromStore()
		if err != nil {
			return fmt.Errorf("failed to get network from store during leave: %v", err)
		}
		extD, err := extN.driver(true)
		if err != nil {
			return fmt.Errorf("failed to leave endpoint: %v", err)
		}
		if err := extD.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); err != nil {
			log.Warnf("driver failed programming external connectivity on endpoint %s: (%s) %v",
				extEp.Name(), extEp.ID(), err)
		}
	}

	if !sb.needDefaultGW() {
		if err := sb.clearDefaultGW(); err != nil {
			log.Warnf("Failure while disconnecting sandbox %s (%s) from gateway network: %v",
				sb.ID(), sb.ContainerID(), err)
		}
	}

	return nil
}