Browse code

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

Support dockerd and system restarts for ipvlan and macvlan networks

elangovan sivanandam authored on 2019/07/27 02:04:34
Showing 5 changed files
... ...
@@ -706,9 +706,10 @@ const overlayDSROptionString = "dsr"
706 706
 // are network specific and modeled in a generic way.
707 707
 func (c *controller) NewNetwork(networkType, name string, id string, options ...NetworkOption) (Network, error) {
708 708
 	var (
709
-		cap *driverapi.Capability
710
-		err error
711
-		t   *network
709
+		cap            *driverapi.Capability
710
+		err            error
711
+		t              *network
712
+		skipCfgEpCount bool
712 713
 	)
713 714
 
714 715
 	if id != "" {
... ...
@@ -803,7 +804,7 @@ func (c *controller) NewNetwork(networkType, name string, id string, options ...
803 803
 		}
804 804
 		network.generic[netlabel.Internal] = network.internal
805 805
 		defer func() {
806
-			if err == nil {
806
+			if err == nil && !skipCfgEpCount {
807 807
 				if err := t.getEpCnt().IncEndpointCnt(); err != nil {
808 808
 					logrus.Warnf("Failed to update reference count for configuration network %q on creation of network %q: %v",
809 809
 						t.Name(), network.Name(), err)
... ...
@@ -824,7 +825,13 @@ func (c *controller) NewNetwork(networkType, name string, id string, options ...
824 824
 
825 825
 	err = c.addNetwork(network)
826 826
 	if err != nil {
827
-		return nil, err
827
+		if strings.Contains(err.Error(), "restoring existing network") {
828
+			// This error can be ignored and set this boolean
829
+			// value to skip a refcount increment for configOnly networks
830
+			skipCfgEpCount = true
831
+		} else {
832
+			return nil, err
833
+		}
828 834
 	}
829 835
 	defer func() {
830 836
 		if err != nil {
... ...
@@ -60,10 +60,14 @@ func (d *driver) CreateNetwork(nid string, option map[string]interface{}, nInfo
60 60
 		// empty parent and --internal are handled the same. Set here to update k/v
61 61
 		config.Internal = true
62 62
 	}
63
-	err = d.createNetwork(config)
63
+	foundExisting, err := d.createNetwork(config)
64 64
 	if err != nil {
65 65
 		return err
66 66
 	}
67
+
68
+	if foundExisting {
69
+		return types.InternalMaskableErrorf("restoring existing network %s", config.ID)
70
+	}
67 71
 	// update persistent db, rollback on fail
68 72
 	err = d.storeUpdate(config)
69 73
 	if err != nil {
... ...
@@ -76,12 +80,18 @@ func (d *driver) CreateNetwork(nid string, option map[string]interface{}, nInfo
76 76
 }
77 77
 
78 78
 // createNetwork is used by new network callbacks and persistent network cache
79
-func (d *driver) createNetwork(config *configuration) error {
79
+func (d *driver) createNetwork(config *configuration) (bool, error) {
80
+	foundExisting := false
80 81
 	networkList := d.getNetworks()
81 82
 	for _, nw := range networkList {
82 83
 		if config.Parent == nw.config.Parent {
83
-			return fmt.Errorf("network %s is already using parent interface %s",
84
-				getDummyName(stringid.TruncateID(nw.config.ID)), config.Parent)
84
+			if config.ID != nw.config.ID {
85
+				return false, fmt.Errorf("network %s is already using parent interface %s",
86
+					getDummyName(stringid.TruncateID(nw.config.ID)), config.Parent)
87
+			}
88
+			logrus.Debugf("Create Network for the same ID %s\n", config.ID)
89
+			foundExisting = true
90
+			break
85 91
 		}
86 92
 	}
87 93
 	if !parentExists(config.Parent) {
... ...
@@ -89,9 +99,10 @@ func (d *driver) createNetwork(config *configuration) error {
89 89
 		if config.Internal {
90 90
 			err := createDummyLink(config.Parent, getDummyName(stringid.TruncateID(config.ID)))
91 91
 			if err != nil {
92
-				return err
92
+				return false, err
93 93
 			}
94 94
 			config.CreatedSlaveLink = true
95
+
95 96
 			// notify the user in logs they have limited communications
96 97
 			if config.Parent == getDummyName(stringid.TruncateID(config.ID)) {
97 98
 				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 {
102 102
 			//  a valid example is 'eth0.10' for a parent iface 'eth0' with a vlan id '10'
103 103
 			err := createVlanLink(config.Parent)
104 104
 			if err != nil {
105
-				return err
105
+				return false, err
106 106
 			}
107 107
 			// if driver created the networks slave link, record it for future deletion
108 108
 			config.CreatedSlaveLink = true
109 109
 		}
110 110
 	}
111
-	n := &network{
112
-		id:        config.ID,
113
-		driver:    d,
114
-		endpoints: endpointTable{},
115
-		config:    config,
111
+	if !foundExisting {
112
+		n := &network{
113
+			id:        config.ID,
114
+			driver:    d,
115
+			endpoints: endpointTable{},
116
+			config:    config,
117
+		}
118
+		// add the network
119
+		d.addNetwork(n)
116 120
 	}
117
-	// add the *network
118
-	d.addNetwork(n)
119 121
 
120
-	return nil
122
+	return foundExisting, nil
121 123
 }
122 124
 
123 125
 // DeleteNetwork the network for the specified driver type
... ...
@@ -55,7 +55,14 @@ func (d *driver) initStore(option map[string]interface{}) error {
55 55
 			return types.InternalErrorf("ipvlan driver failed to initialize data store: %v", err)
56 56
 		}
57 57
 
58
-		return d.populateNetworks()
58
+		err = d.populateNetworks()
59
+		if err != nil {
60
+			return err
61
+		}
62
+		err = d.populateEndpoints()
63
+		if err != nil {
64
+			return err
65
+		}
59 66
 	}
60 67
 
61 68
 	return nil
... ...
@@ -73,7 +80,7 @@ func (d *driver) populateNetworks() error {
73 73
 	}
74 74
 	for _, kvo := range kvol {
75 75
 		config := kvo.(*configuration)
76
-		if err = d.createNetwork(config); err != nil {
76
+		if _, err = d.createNetwork(config); err != nil {
77 77
 			logrus.Warnf("could not create ipvlan network for id %s from persistent state", config.ID)
78 78
 		}
79 79
 	}
... ...
@@ -64,10 +64,15 @@ func (d *driver) CreateNetwork(nid string, option map[string]interface{}, nInfo
64 64
 		// empty parent and --internal are handled the same. Set here to update k/v
65 65
 		config.Internal = true
66 66
 	}
67
-	err = d.createNetwork(config)
67
+	foundExisting, err := d.createNetwork(config)
68 68
 	if err != nil {
69 69
 		return err
70 70
 	}
71
+
72
+	if foundExisting {
73
+		return types.InternalMaskableErrorf("restoring existing network %s", config.ID)
74
+	}
75
+
71 76
 	// update persistent db, rollback on fail
72 77
 	err = d.storeUpdate(config)
73 78
 	if err != nil {
... ...
@@ -80,12 +85,18 @@ func (d *driver) CreateNetwork(nid string, option map[string]interface{}, nInfo
80 80
 }
81 81
 
82 82
 // createNetwork is used by new network callbacks and persistent network cache
83
-func (d *driver) createNetwork(config *configuration) error {
83
+func (d *driver) createNetwork(config *configuration) (bool, error) {
84
+	foundExisting := false
84 85
 	networkList := d.getNetworks()
85 86
 	for _, nw := range networkList {
86 87
 		if config.Parent == nw.config.Parent {
87
-			return fmt.Errorf("network %s is already using parent interface %s",
88
-				getDummyName(stringid.TruncateID(nw.config.ID)), config.Parent)
88
+			if config.ID != nw.config.ID {
89
+				return false, fmt.Errorf("network %s is already using parent interface %s",
90
+					getDummyName(stringid.TruncateID(nw.config.ID)), config.Parent)
91
+			}
92
+			logrus.Debugf("Create Network for the same ID %s\n", config.ID)
93
+			foundExisting = true
94
+			break
89 95
 		}
90 96
 	}
91 97
 	if !parentExists(config.Parent) {
... ...
@@ -93,7 +104,7 @@ func (d *driver) createNetwork(config *configuration) error {
93 93
 		if config.Internal {
94 94
 			err := createDummyLink(config.Parent, getDummyName(stringid.TruncateID(config.ID)))
95 95
 			if err != nil {
96
-				return err
96
+				return false, err
97 97
 			}
98 98
 			config.CreatedSlaveLink = true
99 99
 			// notify the user in logs they have limited communications
... ...
@@ -106,22 +117,24 @@ func (d *driver) createNetwork(config *configuration) error {
106 106
 			//  a valid example is 'eth0.10' for a parent iface 'eth0' with a vlan id '10'
107 107
 			err := createVlanLink(config.Parent)
108 108
 			if err != nil {
109
-				return err
109
+				return false, err
110 110
 			}
111 111
 			// if driver created the networks slave link, record it for future deletion
112 112
 			config.CreatedSlaveLink = true
113 113
 		}
114 114
 	}
115
-	n := &network{
116
-		id:        config.ID,
117
-		driver:    d,
118
-		endpoints: endpointTable{},
119
-		config:    config,
115
+	if !foundExisting {
116
+		n := &network{
117
+			id:        config.ID,
118
+			driver:    d,
119
+			endpoints: endpointTable{},
120
+			config:    config,
121
+		}
122
+		// add the network
123
+		d.addNetwork(n)
120 124
 	}
121
-	// add the *network
122
-	d.addNetwork(n)
123 125
 
124
-	return nil
126
+	return foundExisting, nil
125 127
 }
126 128
 
127 129
 // DeleteNetwork deletes the network for the specified driver type
... ...
@@ -55,7 +55,15 @@ func (d *driver) initStore(option map[string]interface{}) error {
55 55
 			return types.InternalErrorf("macvlan driver failed to initialize data store: %v", err)
56 56
 		}
57 57
 
58
-		return d.populateNetworks()
58
+		err = d.populateNetworks()
59
+		if err != nil {
60
+			return err
61
+		}
62
+		err = d.populateEndpoints()
63
+		if err != nil {
64
+			return err
65
+		}
66
+
59 67
 	}
60 68
 
61 69
 	return nil
... ...
@@ -73,7 +81,7 @@ func (d *driver) populateNetworks() error {
73 73
 	}
74 74
 	for _, kvo := range kvol {
75 75
 		config := kvo.(*configuration)
76
-		if err = d.createNetwork(config); err != nil {
76
+		if _, err = d.createNetwork(config); err != nil {
77 77
 			logrus.Warnf("Could not create macvlan network for id %s from persistent state", config.ID)
78 78
 		}
79 79
 	}