Support dockerd and system restarts for ipvlan and macvlan networks
| ... | ... |
@@ -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 |
} |