فهرست منبع

Merge pull request #2415 from arkodg/ipvlan-docker-restart-issue

Support dockerd and system restarts for ipvlan and macvlan networks
elangovan sivanandam 6 سال پیش
والد
کامیت
a79bbdb5f9

+ 12 - 5
libnetwork/controller.go

@@ -706,9 +706,10 @@ const overlayDSROptionString = "dsr"
 // are network specific and modeled in a generic way.
 // are network specific and modeled in a generic way.
 func (c *controller) NewNetwork(networkType, name string, id string, options ...NetworkOption) (Network, error) {
 func (c *controller) NewNetwork(networkType, name string, id string, options ...NetworkOption) (Network, error) {
 	var (
 	var (
-		cap *driverapi.Capability
-		err error
-		t   *network
+		cap            *driverapi.Capability
+		err            error
+		t              *network
+		skipCfgEpCount bool
 	)
 	)
 
 
 	if id != "" {
 	if id != "" {
@@ -803,7 +804,7 @@ func (c *controller) NewNetwork(networkType, name string, id string, options ...
 		}
 		}
 		network.generic[netlabel.Internal] = network.internal
 		network.generic[netlabel.Internal] = network.internal
 		defer func() {
 		defer func() {
-			if err == nil {
+			if err == nil && !skipCfgEpCount {
 				if err := t.getEpCnt().IncEndpointCnt(); err != nil {
 				if err := t.getEpCnt().IncEndpointCnt(); err != nil {
 					logrus.Warnf("Failed to update reference count for configuration network %q on creation of network %q: %v",
 					logrus.Warnf("Failed to update reference count for configuration network %q on creation of network %q: %v",
 						t.Name(), network.Name(), err)
 						t.Name(), network.Name(), err)
@@ -824,7 +825,13 @@ func (c *controller) NewNetwork(networkType, name string, id string, options ...
 
 
 	err = c.addNetwork(network)
 	err = c.addNetwork(network)
 	if err != nil {
 	if err != nil {
-		return nil, err
+		if strings.Contains(err.Error(), "restoring existing network") {
+			// This error can be ignored and set this boolean
+			// value to skip a refcount increment for configOnly networks
+			skipCfgEpCount = true
+		} else {
+			return nil, err
+		}
 	}
 	}
 	defer func() {
 	defer func() {
 		if err != nil {
 		if err != nil {

+ 27 - 14
libnetwork/drivers/ipvlan/ipvlan_network.go

@@ -60,10 +60,14 @@ func (d *driver) CreateNetwork(nid string, option map[string]interface{}, nInfo
 		// empty parent and --internal are handled the same. Set here to update k/v
 		// empty parent and --internal are handled the same. Set here to update k/v
 		config.Internal = true
 		config.Internal = true
 	}
 	}
-	err = d.createNetwork(config)
+	foundExisting, err := d.createNetwork(config)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
+
+	if foundExisting {
+		return types.InternalMaskableErrorf("restoring existing network %s", config.ID)
+	}
 	// update persistent db, rollback on fail
 	// update persistent db, rollback on fail
 	err = d.storeUpdate(config)
 	err = d.storeUpdate(config)
 	if err != nil {
 	if err != nil {
@@ -76,12 +80,18 @@ func (d *driver) CreateNetwork(nid string, option map[string]interface{}, nInfo
 }
 }
 
 
 // createNetwork is used by new network callbacks and persistent network cache
 // createNetwork is used by new network callbacks and persistent network cache
-func (d *driver) createNetwork(config *configuration) error {
+func (d *driver) createNetwork(config *configuration) (bool, error) {
+	foundExisting := false
 	networkList := d.getNetworks()
 	networkList := d.getNetworks()
 	for _, nw := range networkList {
 	for _, nw := range networkList {
 		if config.Parent == nw.config.Parent {
 		if config.Parent == nw.config.Parent {
-			return fmt.Errorf("network %s is already using parent interface %s",
-				getDummyName(stringid.TruncateID(nw.config.ID)), config.Parent)
+			if config.ID != nw.config.ID {
+				return false, fmt.Errorf("network %s is already using parent interface %s",
+					getDummyName(stringid.TruncateID(nw.config.ID)), config.Parent)
+			}
+			logrus.Debugf("Create Network for the same ID %s\n", config.ID)
+			foundExisting = true
+			break
 		}
 		}
 	}
 	}
 	if !parentExists(config.Parent) {
 	if !parentExists(config.Parent) {
@@ -89,9 +99,10 @@ func (d *driver) createNetwork(config *configuration) error {
 		if config.Internal {
 		if config.Internal {
 			err := createDummyLink(config.Parent, getDummyName(stringid.TruncateID(config.ID)))
 			err := createDummyLink(config.Parent, getDummyName(stringid.TruncateID(config.ID)))
 			if err != nil {
 			if err != nil {
-				return err
+				return false, err
 			}
 			}
 			config.CreatedSlaveLink = true
 			config.CreatedSlaveLink = true
+
 			// notify the user in logs they have limited communications
 			// notify the user in logs they have limited communications
 			if config.Parent == getDummyName(stringid.TruncateID(config.ID)) {
 			if config.Parent == getDummyName(stringid.TruncateID(config.ID)) {
 				logrus.Debugf("Empty -o parent= and --internal flags limit communications to other containers inside of network: %s",
 				logrus.Debugf("Empty -o parent= and --internal flags limit communications to other containers inside of network: %s",
@@ -102,22 +113,24 @@ func (d *driver) createNetwork(config *configuration) error {
 			//  a valid example is 'eth0.10' for a parent iface 'eth0' with a vlan id '10'
 			//  a valid example is 'eth0.10' for a parent iface 'eth0' with a vlan id '10'
 			err := createVlanLink(config.Parent)
 			err := createVlanLink(config.Parent)
 			if err != nil {
 			if err != nil {
-				return err
+				return false, err
 			}
 			}
 			// if driver created the networks slave link, record it for future deletion
 			// if driver created the networks slave link, record it for future deletion
 			config.CreatedSlaveLink = true
 			config.CreatedSlaveLink = true
 		}
 		}
 	}
 	}
-	n := &network{
-		id:        config.ID,
-		driver:    d,
-		endpoints: endpointTable{},
-		config:    config,
+	if !foundExisting {
+		n := &network{
+			id:        config.ID,
+			driver:    d,
+			endpoints: endpointTable{},
+			config:    config,
+		}
+		// add the network
+		d.addNetwork(n)
 	}
 	}
-	// add the *network
-	d.addNetwork(n)
 
 
-	return nil
+	return foundExisting, nil
 }
 }
 
 
 // DeleteNetwork the network for the specified driver type
 // DeleteNetwork the network for the specified driver type

+ 9 - 2
libnetwork/drivers/ipvlan/ipvlan_store.go

@@ -55,7 +55,14 @@ func (d *driver) initStore(option map[string]interface{}) error {
 			return types.InternalErrorf("ipvlan driver failed to initialize data store: %v", err)
 			return types.InternalErrorf("ipvlan driver failed to initialize data store: %v", err)
 		}
 		}
 
 
-		return d.populateNetworks()
+		err = d.populateNetworks()
+		if err != nil {
+			return err
+		}
+		err = d.populateEndpoints()
+		if err != nil {
+			return err
+		}
 	}
 	}
 
 
 	return nil
 	return nil
@@ -73,7 +80,7 @@ func (d *driver) populateNetworks() error {
 	}
 	}
 	for _, kvo := range kvol {
 	for _, kvo := range kvol {
 		config := kvo.(*configuration)
 		config := kvo.(*configuration)
-		if err = d.createNetwork(config); err != nil {
+		if _, err = d.createNetwork(config); err != nil {
 			logrus.Warnf("could not create ipvlan network for id %s from persistent state", config.ID)
 			logrus.Warnf("could not create ipvlan network for id %s from persistent state", config.ID)
 		}
 		}
 	}
 	}

+ 27 - 14
libnetwork/drivers/macvlan/macvlan_network.go

@@ -64,10 +64,15 @@ func (d *driver) CreateNetwork(nid string, option map[string]interface{}, nInfo
 		// empty parent and --internal are handled the same. Set here to update k/v
 		// empty parent and --internal are handled the same. Set here to update k/v
 		config.Internal = true
 		config.Internal = true
 	}
 	}
-	err = d.createNetwork(config)
+	foundExisting, err := d.createNetwork(config)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
+
+	if foundExisting {
+		return types.InternalMaskableErrorf("restoring existing network %s", config.ID)
+	}
+
 	// update persistent db, rollback on fail
 	// update persistent db, rollback on fail
 	err = d.storeUpdate(config)
 	err = d.storeUpdate(config)
 	if err != nil {
 	if err != nil {
@@ -80,12 +85,18 @@ func (d *driver) CreateNetwork(nid string, option map[string]interface{}, nInfo
 }
 }
 
 
 // createNetwork is used by new network callbacks and persistent network cache
 // createNetwork is used by new network callbacks and persistent network cache
-func (d *driver) createNetwork(config *configuration) error {
+func (d *driver) createNetwork(config *configuration) (bool, error) {
+	foundExisting := false
 	networkList := d.getNetworks()
 	networkList := d.getNetworks()
 	for _, nw := range networkList {
 	for _, nw := range networkList {
 		if config.Parent == nw.config.Parent {
 		if config.Parent == nw.config.Parent {
-			return fmt.Errorf("network %s is already using parent interface %s",
-				getDummyName(stringid.TruncateID(nw.config.ID)), config.Parent)
+			if config.ID != nw.config.ID {
+				return false, fmt.Errorf("network %s is already using parent interface %s",
+					getDummyName(stringid.TruncateID(nw.config.ID)), config.Parent)
+			}
+			logrus.Debugf("Create Network for the same ID %s\n", config.ID)
+			foundExisting = true
+			break
 		}
 		}
 	}
 	}
 	if !parentExists(config.Parent) {
 	if !parentExists(config.Parent) {
@@ -93,7 +104,7 @@ func (d *driver) createNetwork(config *configuration) error {
 		if config.Internal {
 		if config.Internal {
 			err := createDummyLink(config.Parent, getDummyName(stringid.TruncateID(config.ID)))
 			err := createDummyLink(config.Parent, getDummyName(stringid.TruncateID(config.ID)))
 			if err != nil {
 			if err != nil {
-				return err
+				return false, err
 			}
 			}
 			config.CreatedSlaveLink = true
 			config.CreatedSlaveLink = true
 			// notify the user in logs they have limited communications
 			// notify the user in logs they have limited communications
@@ -106,22 +117,24 @@ func (d *driver) createNetwork(config *configuration) error {
 			//  a valid example is 'eth0.10' for a parent iface 'eth0' with a vlan id '10'
 			//  a valid example is 'eth0.10' for a parent iface 'eth0' with a vlan id '10'
 			err := createVlanLink(config.Parent)
 			err := createVlanLink(config.Parent)
 			if err != nil {
 			if err != nil {
-				return err
+				return false, err
 			}
 			}
 			// if driver created the networks slave link, record it for future deletion
 			// if driver created the networks slave link, record it for future deletion
 			config.CreatedSlaveLink = true
 			config.CreatedSlaveLink = true
 		}
 		}
 	}
 	}
-	n := &network{
-		id:        config.ID,
-		driver:    d,
-		endpoints: endpointTable{},
-		config:    config,
+	if !foundExisting {
+		n := &network{
+			id:        config.ID,
+			driver:    d,
+			endpoints: endpointTable{},
+			config:    config,
+		}
+		// add the network
+		d.addNetwork(n)
 	}
 	}
-	// add the *network
-	d.addNetwork(n)
 
 
-	return nil
+	return foundExisting, nil
 }
 }
 
 
 // DeleteNetwork deletes the network for the specified driver type
 // DeleteNetwork deletes the network for the specified driver type

+ 10 - 2
libnetwork/drivers/macvlan/macvlan_store.go

@@ -55,7 +55,15 @@ func (d *driver) initStore(option map[string]interface{}) error {
 			return types.InternalErrorf("macvlan driver failed to initialize data store: %v", err)
 			return types.InternalErrorf("macvlan driver failed to initialize data store: %v", err)
 		}
 		}
 
 
-		return d.populateNetworks()
+		err = d.populateNetworks()
+		if err != nil {
+			return err
+		}
+		err = d.populateEndpoints()
+		if err != nil {
+			return err
+		}
+
 	}
 	}
 
 
 	return nil
 	return nil
@@ -73,7 +81,7 @@ func (d *driver) populateNetworks() error {
 	}
 	}
 	for _, kvo := range kvol {
 	for _, kvo := range kvol {
 		config := kvo.(*configuration)
 		config := kvo.(*configuration)
-		if err = d.createNetwork(config); err != nil {
+		if _, err = d.createNetwork(config); err != nil {
 			logrus.Warnf("Could not create macvlan network for id %s from persistent state", config.ID)
 			logrus.Warnf("Could not create macvlan network for id %s from persistent state", config.ID)
 		}
 		}
 	}
 	}