Vendoring libnetowrk @5537cb4
| ... | ... |
@@ -23,7 +23,7 @@ github.com/RackSec/srslog 456df3a81436d29ba874f3590eeeee25d666f8a5 |
| 23 | 23 |
github.com/imdario/mergo 0.2.1 |
| 24 | 24 |
|
| 25 | 25 |
#get libnetwork packages |
| 26 |
-github.com/docker/libnetwork 802895f7f342253a60f1666565e84707851a94f2 |
|
| 26 |
+github.com/docker/libnetwork 5537cb4b15c16eff2619db126ead3271e0ab45eb |
|
| 27 | 27 |
github.com/docker/go-events 18b43f1bc85d9cdd42c05a6cd2d444c7a200a894 |
| 28 | 28 |
github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 |
| 29 | 29 |
github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec |
| ... | ... |
@@ -413,6 +413,7 @@ func (d *driver) updateKeys(newKey, primary, pruneKey *key) error {
|
| 413 | 413 |
priIdx = -1 |
| 414 | 414 |
delIdx = -1 |
| 415 | 415 |
lIP = net.ParseIP(d.bindAddress) |
| 416 |
+ aIP = net.ParseIP(d.advertiseAddress) |
|
| 416 | 417 |
) |
| 417 | 418 |
|
| 418 | 419 |
d.Lock() |
| ... | ... |
@@ -440,7 +441,7 @@ func (d *driver) updateKeys(newKey, primary, pruneKey *key) error {
|
| 440 | 440 |
|
| 441 | 441 |
d.secMapWalk(func(rIPs string, spis []*spi) ([]*spi, bool) {
|
| 442 | 442 |
rIP := net.ParseIP(rIPs) |
| 443 |
- return updateNodeKey(lIP, rIP, spis, d.keys, newIdx, priIdx, delIdx), false |
|
| 443 |
+ return updateNodeKey(lIP, aIP, rIP, spis, d.keys, newIdx, priIdx, delIdx), false |
|
| 444 | 444 |
}) |
| 445 | 445 |
|
| 446 | 446 |
d.Lock() |
| ... | ... |
@@ -471,7 +472,7 @@ func (d *driver) updateKeys(newKey, primary, pruneKey *key) error {
|
| 471 | 471 |
*********************************************************/ |
| 472 | 472 |
|
| 473 | 473 |
// Spis and keys are sorted in such away the one in position 0 is the primary |
| 474 |
-func updateNodeKey(lIP, rIP net.IP, idxs []*spi, curKeys []*key, newIdx, priIdx, delIdx int) []*spi {
|
|
| 474 |
+func updateNodeKey(lIP, aIP, rIP net.IP, idxs []*spi, curKeys []*key, newIdx, priIdx, delIdx int) []*spi {
|
|
| 475 | 475 |
logrus.Debugf("Updating keys for node: %s (%d,%d,%d)", rIP, newIdx, priIdx, delIdx)
|
| 476 | 476 |
|
| 477 | 477 |
spis := idxs |
| ... | ... |
@@ -480,8 +481,8 @@ func updateNodeKey(lIP, rIP net.IP, idxs []*spi, curKeys []*key, newIdx, priIdx, |
| 480 | 480 |
// add new |
| 481 | 481 |
if newIdx != -1 {
|
| 482 | 482 |
spis = append(spis, &spi{
|
| 483 |
- forward: buildSPI(lIP, rIP, curKeys[newIdx].tag), |
|
| 484 |
- reverse: buildSPI(rIP, lIP, curKeys[newIdx].tag), |
|
| 483 |
+ forward: buildSPI(aIP, rIP, curKeys[newIdx].tag), |
|
| 484 |
+ reverse: buildSPI(rIP, aIP, curKeys[newIdx].tag), |
|
| 485 | 485 |
}) |
| 486 | 486 |
} |
| 487 | 487 |
|
| ... | ... |
@@ -612,13 +612,13 @@ func (n *network) initSandbox(restore bool) error {
|
| 612 | 612 |
var nlSock *nl.NetlinkSocket |
| 613 | 613 |
sbox.InvokeFunc(func() {
|
| 614 | 614 |
nlSock, err = nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_NEIGH) |
| 615 |
- if err != nil {
|
|
| 616 |
- err = fmt.Errorf("failed to subscribe to neighbor group netlink messages")
|
|
| 617 |
- } |
|
| 618 | 615 |
}) |
| 619 | 616 |
|
| 620 |
- if nlSock != nil {
|
|
| 617 |
+ if err == nil {
|
|
| 621 | 618 |
go n.watchMiss(nlSock) |
| 619 |
+ } else {
|
|
| 620 |
+ logrus.Errorf("failed to subscribe to neighbor group netlink messages for overlay network %s in sbox %s: %v",
|
|
| 621 |
+ n.id, sbox.Key(), err) |
|
| 622 | 622 |
} |
| 623 | 623 |
|
| 624 | 624 |
return nil |
| ... | ... |
@@ -644,6 +644,9 @@ func (n *network) watchMiss(nlSock *nl.NetlinkSocket) {
|
| 644 | 644 |
} |
| 645 | 645 |
|
| 646 | 646 |
if neigh.IP.To4() == nil {
|
| 647 |
+ if neigh.HardwareAddr != nil {
|
|
| 648 |
+ logrus.Debugf("Miss notification, l2 mac %v", neigh.HardwareAddr)
|
|
| 649 |
+ } |
|
| 647 | 650 |
continue |
| 648 | 651 |
} |
| 649 | 652 |
|
| ... | ... |
@@ -73,7 +73,7 @@ func (d *driver) serfJoin(neighIP string) error {
|
| 73 | 73 |
if neighIP == "" {
|
| 74 | 74 |
return fmt.Errorf("no neighbor to join")
|
| 75 | 75 |
} |
| 76 |
- if _, err := d.serfInstance.Join([]string{neighIP}, false); err != nil {
|
|
| 76 |
+ if _, err := d.serfInstance.Join([]string{neighIP}, true); err != nil {
|
|
| 77 | 77 |
return fmt.Errorf("Failed to join the cluster at neigh IP %s: %v",
|
| 78 | 78 |
neighIP, err) |
| 79 | 79 |
} |
| ... | ... |
@@ -94,8 +94,8 @@ func (d *driver) notifyEvent(event ovNotify) {
|
| 94 | 94 |
} |
| 95 | 95 |
|
| 96 | 96 |
func (d *driver) processEvent(u serf.UserEvent) {
|
| 97 |
- logrus.Debugf("Received user event name:%s, payload:%s\n", u.Name,
|
|
| 98 |
- string(u.Payload)) |
|
| 97 |
+ logrus.Debugf("Received user event name:%s, payload:%s LTime:%d \n", u.Name,
|
|
| 98 |
+ string(u.Payload), uint64(u.LTime)) |
|
| 99 | 99 |
|
| 100 | 100 |
var dummy, action, vtepStr, nid, eid, ipStr, maskStr, macStr string |
| 101 | 101 |
if _, err := fmt.Sscan(u.Name, &dummy, &vtepStr, &nid, &eid); err != nil {
|
| ... | ... |
@@ -146,6 +146,7 @@ func (d *driver) processQuery(q *serf.Query) {
|
| 146 | 146 |
return |
| 147 | 147 |
} |
| 148 | 148 |
|
| 149 |
+ logrus.Debugf("Sending peer query resp mac %s, mask %s, vtep %s", peerMac, net.IP(peerIPMask), vtep)
|
|
| 149 | 150 |
q.Respond([]byte(fmt.Sprintf("%s %s %s", peerMac.String(), net.IP(peerIPMask).String(), vtep.String())))
|
| 150 | 151 |
} |
| 151 | 152 |
|
| ... | ... |
@@ -173,6 +174,7 @@ func (d *driver) resolvePeer(nid string, peerIP net.IP) (net.HardwareAddr, net.I |
| 173 | 173 |
return nil, nil, nil, fmt.Errorf("failed to parse mac: %v", err)
|
| 174 | 174 |
} |
| 175 | 175 |
|
| 176 |
+ logrus.Debugf("Received peer query response, mac %s, vtep %s, mask %s", macStr, vtepStr, maskStr)
|
|
| 176 | 177 |
return mac, net.IPMask(net.ParseIP(maskStr).To4()), net.ParseIP(vtepStr), nil |
| 177 | 178 |
|
| 178 | 179 |
case <-time.After(time.Second): |
| ... | ... |
@@ -48,6 +48,7 @@ type driver struct {
|
| 48 | 48 |
vxlanIdm *idm.Idm |
| 49 | 49 |
once sync.Once |
| 50 | 50 |
joinOnce sync.Once |
| 51 |
+ localJoinOnce sync.Once |
|
| 51 | 52 |
keys []*key |
| 52 | 53 |
sync.Mutex |
| 53 | 54 |
} |
| ... | ... |
@@ -241,6 +242,12 @@ func (d *driver) nodeJoin(advertiseAddress, bindAddress string, self bool) {
|
| 241 | 241 |
d.bindAddress = bindAddress |
| 242 | 242 |
d.Unlock() |
| 243 | 243 |
|
| 244 |
+ // If containers are already running on this network update the |
|
| 245 |
+ // advertiseaddress in the peerDB |
|
| 246 |
+ d.localJoinOnce.Do(func() {
|
|
| 247 |
+ d.peerDBUpdateSelf() |
|
| 248 |
+ }) |
|
| 249 |
+ |
|
| 244 | 250 |
// If there is no cluster store there is no need to start serf. |
| 245 | 251 |
if d.store != nil {
|
| 246 | 252 |
if err := validateSelf(advertiseAddress); err != nil {
|
| ... | ... |
@@ -80,25 +80,29 @@ func (d *driver) peerDbWalk(f func(string, *peerKey, *peerEntry) bool) error {
|
| 80 | 80 |
func (d *driver) peerDbNetworkWalk(nid string, f func(*peerKey, *peerEntry) bool) error {
|
| 81 | 81 |
d.peerDb.Lock() |
| 82 | 82 |
pMap, ok := d.peerDb.mp[nid] |
| 83 |
+ d.peerDb.Unlock() |
|
| 84 |
+ |
|
| 83 | 85 |
if !ok {
|
| 84 |
- d.peerDb.Unlock() |
|
| 85 | 86 |
return nil |
| 86 | 87 |
} |
| 87 |
- d.peerDb.Unlock() |
|
| 88 |
+ |
|
| 89 |
+ mp := map[string]peerEntry{}
|
|
| 88 | 90 |
|
| 89 | 91 |
pMap.Lock() |
| 90 | 92 |
for pKeyStr, pEntry := range pMap.mp {
|
| 93 |
+ mp[pKeyStr] = pEntry |
|
| 94 |
+ } |
|
| 95 |
+ pMap.Unlock() |
|
| 96 |
+ |
|
| 97 |
+ for pKeyStr, pEntry := range mp {
|
|
| 91 | 98 |
var pKey peerKey |
| 92 | 99 |
if _, err := fmt.Sscan(pKeyStr, &pKey); err != nil {
|
| 93 | 100 |
logrus.Warnf("Peer key scan on network %s failed: %v", nid, err)
|
| 94 | 101 |
} |
| 95 |
- |
|
| 96 | 102 |
if f(&pKey, &pEntry) {
|
| 97 |
- pMap.Unlock() |
|
| 98 | 103 |
return nil |
| 99 | 104 |
} |
| 100 | 105 |
} |
| 101 |
- pMap.Unlock() |
|
| 102 | 106 |
|
| 103 | 107 |
return nil |
| 104 | 108 |
} |
| ... | ... |
@@ -363,3 +367,12 @@ func (d *driver) pushLocalDb() {
|
| 363 | 363 |
return false |
| 364 | 364 |
}) |
| 365 | 365 |
} |
| 366 |
+ |
|
| 367 |
+func (d *driver) peerDBUpdateSelf() {
|
|
| 368 |
+ d.peerDbWalk(func(nid string, pkey *peerKey, pEntry *peerEntry) bool {
|
|
| 369 |
+ if pEntry.isLocal {
|
|
| 370 |
+ pEntry.vtep = net.ParseIP(d.advertiseAddress) |
|
| 371 |
+ } |
|
| 372 |
+ return false |
|
| 373 |
+ }) |
|
| 374 |
+} |
| ... | ... |
@@ -26,10 +26,6 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, |
| 26 | 26 |
return fmt.Errorf("could not find endpoint with id %s", eid)
|
| 27 | 27 |
} |
| 28 | 28 |
|
| 29 |
- if err := d.writeEndpointToStore(ep); err != nil {
|
|
| 30 |
- return fmt.Errorf("failed to update overlay endpoint %s to local data store: %v", ep.id[0:7], err)
|
|
| 31 |
- } |
|
| 32 |
- |
|
| 33 | 29 |
buf, err := proto.Marshal(&PeerRecord{
|
| 34 | 30 |
EndpointIP: ep.addr.String(), |
| 35 | 31 |
EndpointMAC: ep.mac.String(), |
| ... | ... |
@@ -43,9 +39,6 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, |
| 43 | 43 |
if err := jinfo.AddTableEntry(ovPeerTable, eid, buf); err != nil {
|
| 44 | 44 |
logrus.Errorf("overlay: Failed adding table entry to joininfo: %v", err)
|
| 45 | 45 |
} |
| 46 |
- |
|
| 47 |
- d.pushLocalEndpointEvent("join", nid, eid)
|
|
| 48 |
- |
|
| 49 | 46 |
return nil |
| 50 | 47 |
} |
| 51 | 48 |
|
| ... | ... |
@@ -106,7 +99,5 @@ func (d *driver) Leave(nid, eid string) error {
|
| 106 | 106 |
return err |
| 107 | 107 |
} |
| 108 | 108 |
|
| 109 |
- d.pushLocalEndpointEvent("leave", nid, eid)
|
|
| 110 |
- |
|
| 111 | 109 |
return nil |
| 112 | 110 |
} |
| ... | ... |
@@ -7,9 +7,7 @@ import ( |
| 7 | 7 |
|
| 8 | 8 |
"github.com/Microsoft/hcsshim" |
| 9 | 9 |
"github.com/Sirupsen/logrus" |
| 10 |
- "github.com/docker/libnetwork/datastore" |
|
| 11 | 10 |
"github.com/docker/libnetwork/driverapi" |
| 12 |
- "github.com/docker/libnetwork/types" |
|
| 13 | 11 |
) |
| 14 | 12 |
|
| 15 | 13 |
type endpointTable map[string]*endpoint |
| ... | ... |
@@ -23,8 +21,6 @@ type endpoint struct {
|
| 23 | 23 |
remote bool |
| 24 | 24 |
mac net.HardwareAddr |
| 25 | 25 |
addr *net.IPNet |
| 26 |
- dbExists bool |
|
| 27 |
- dbIndex uint64 |
|
| 28 | 26 |
} |
| 29 | 27 |
|
| 30 | 28 |
func validateID(nid, eid string) error {
|
| ... | ... |
@@ -67,6 +63,7 @@ func (n *network) removeEndpointWithAddress(addr *net.IPNet) {
|
| 67 | 67 |
break |
| 68 | 68 |
} |
| 69 | 69 |
} |
| 70 |
+ |
|
| 70 | 71 |
if networkEndpoint != nil {
|
| 71 | 72 |
delete(n.endpoints, networkEndpoint.id) |
| 72 | 73 |
} |
| ... | ... |
@@ -79,10 +76,6 @@ func (n *network) removeEndpointWithAddress(addr *net.IPNet) {
|
| 79 | 79 |
if err != nil {
|
| 80 | 80 |
logrus.Debugf("Failed to delete stale overlay endpoint (%s) from hns", networkEndpoint.id[0:7])
|
| 81 | 81 |
} |
| 82 |
- |
|
| 83 |
- if err := n.driver.deleteEndpointFromStore(networkEndpoint); err != nil {
|
|
| 84 |
- logrus.Debugf("Failed to delete stale overlay endpoint (%s) from store", networkEndpoint.id[0:7])
|
|
| 85 |
- } |
|
| 86 | 82 |
} |
| 87 | 83 |
} |
| 88 | 84 |
|
| ... | ... |
@@ -93,19 +86,23 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, |
| 93 | 93 |
return err |
| 94 | 94 |
} |
| 95 | 95 |
|
| 96 |
- // Since we perform lazy configuration make sure we try |
|
| 97 |
- // configuring the driver when we enter CreateEndpoint since |
|
| 98 |
- // CreateNetwork may not be called in every node. |
|
| 99 |
- if err := d.configure(); err != nil {
|
|
| 100 |
- return err |
|
| 101 |
- } |
|
| 102 |
- |
|
| 103 | 96 |
n := d.network(nid) |
| 104 | 97 |
if n == nil {
|
| 105 | 98 |
return fmt.Errorf("network id %q not found", nid)
|
| 106 | 99 |
} |
| 107 | 100 |
|
| 108 |
- ep := &endpoint{
|
|
| 101 |
+ ep := n.endpoint(eid) |
|
| 102 |
+ if ep != nil {
|
|
| 103 |
+ logrus.Debugf("Deleting stale endpoint %s", eid)
|
|
| 104 |
+ n.deleteEndpoint(eid) |
|
| 105 |
+ |
|
| 106 |
+ _, err := hcsshim.HNSEndpointRequest("DELETE", ep.profileId, "")
|
|
| 107 |
+ if err != nil {
|
|
| 108 |
+ return err |
|
| 109 |
+ } |
|
| 110 |
+ } |
|
| 111 |
+ |
|
| 112 |
+ ep = &endpoint{
|
|
| 109 | 113 |
id: eid, |
| 110 | 114 |
nid: n.id, |
| 111 | 115 |
addr: ifInfo.Address(), |
| ... | ... |
@@ -123,6 +120,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, |
| 123 | 123 |
// Todo: Add port bindings and qos policies here |
| 124 | 124 |
|
| 125 | 125 |
hnsEndpoint := &hcsshim.HNSEndpoint{
|
| 126 |
+ Name: eid, |
|
| 126 | 127 |
VirtualNetwork: n.hnsId, |
| 127 | 128 |
IPAddress: ep.addr.IP, |
| 128 | 129 |
EnableInternalDNS: true, |
| ... | ... |
@@ -167,9 +165,6 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, |
| 167 | 167 |
} |
| 168 | 168 |
|
| 169 | 169 |
n.addEndpoint(ep) |
| 170 |
- if err := d.writeEndpointToStore(ep); err != nil {
|
|
| 171 |
- return fmt.Errorf("failed to update overlay endpoint %s to local store: %v", ep.id[0:7], err)
|
|
| 172 |
- } |
|
| 173 | 170 |
|
| 174 | 171 |
return nil |
| 175 | 172 |
} |
| ... | ... |
@@ -191,10 +186,6 @@ func (d *driver) DeleteEndpoint(nid, eid string) error {
|
| 191 | 191 |
|
| 192 | 192 |
n.deleteEndpoint(eid) |
| 193 | 193 |
|
| 194 |
- if err := d.deleteEndpointFromStore(ep); err != nil {
|
|
| 195 |
- logrus.Warnf("Failed to delete overlay endpoint %s from local store: %v", ep.id[0:7], err)
|
|
| 196 |
- } |
|
| 197 |
- |
|
| 198 | 194 |
_, err := hcsshim.HNSEndpointRequest("DELETE", ep.profileId, "")
|
| 199 | 195 |
if err != nil {
|
| 200 | 196 |
return err |
| ... | ... |
@@ -223,124 +214,3 @@ func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, erro
|
| 223 | 223 |
data["AllowUnqualifiedDNSQuery"] = true |
| 224 | 224 |
return data, nil |
| 225 | 225 |
} |
| 226 |
- |
|
| 227 |
-func (d *driver) deleteEndpointFromStore(e *endpoint) error {
|
|
| 228 |
- if d.localStore == nil {
|
|
| 229 |
- return fmt.Errorf("overlay local store not initialized, ep not deleted")
|
|
| 230 |
- } |
|
| 231 |
- |
|
| 232 |
- if err := d.localStore.DeleteObjectAtomic(e); err != nil {
|
|
| 233 |
- return err |
|
| 234 |
- } |
|
| 235 |
- |
|
| 236 |
- return nil |
|
| 237 |
-} |
|
| 238 |
- |
|
| 239 |
-func (d *driver) writeEndpointToStore(e *endpoint) error {
|
|
| 240 |
- if d.localStore == nil {
|
|
| 241 |
- return fmt.Errorf("overlay local store not initialized, ep not added")
|
|
| 242 |
- } |
|
| 243 |
- |
|
| 244 |
- if err := d.localStore.PutObjectAtomic(e); err != nil {
|
|
| 245 |
- return err |
|
| 246 |
- } |
|
| 247 |
- return nil |
|
| 248 |
-} |
|
| 249 |
- |
|
| 250 |
-func (ep *endpoint) DataScope() string {
|
|
| 251 |
- return datastore.LocalScope |
|
| 252 |
-} |
|
| 253 |
- |
|
| 254 |
-func (ep *endpoint) New() datastore.KVObject {
|
|
| 255 |
- return &endpoint{}
|
|
| 256 |
-} |
|
| 257 |
- |
|
| 258 |
-func (ep *endpoint) CopyTo(o datastore.KVObject) error {
|
|
| 259 |
- dstep := o.(*endpoint) |
|
| 260 |
- *dstep = *ep |
|
| 261 |
- return nil |
|
| 262 |
-} |
|
| 263 |
- |
|
| 264 |
-func (ep *endpoint) Key() []string {
|
|
| 265 |
- return []string{overlayEndpointPrefix, ep.id}
|
|
| 266 |
-} |
|
| 267 |
- |
|
| 268 |
-func (ep *endpoint) KeyPrefix() []string {
|
|
| 269 |
- return []string{overlayEndpointPrefix}
|
|
| 270 |
-} |
|
| 271 |
- |
|
| 272 |
-func (ep *endpoint) Index() uint64 {
|
|
| 273 |
- return ep.dbIndex |
|
| 274 |
-} |
|
| 275 |
- |
|
| 276 |
-func (ep *endpoint) SetIndex(index uint64) {
|
|
| 277 |
- ep.dbIndex = index |
|
| 278 |
- ep.dbExists = true |
|
| 279 |
-} |
|
| 280 |
- |
|
| 281 |
-func (ep *endpoint) Exists() bool {
|
|
| 282 |
- return ep.dbExists |
|
| 283 |
-} |
|
| 284 |
- |
|
| 285 |
-func (ep *endpoint) Skip() bool {
|
|
| 286 |
- return false |
|
| 287 |
-} |
|
| 288 |
- |
|
| 289 |
-func (ep *endpoint) Value() []byte {
|
|
| 290 |
- b, err := json.Marshal(ep) |
|
| 291 |
- if err != nil {
|
|
| 292 |
- return nil |
|
| 293 |
- } |
|
| 294 |
- return b |
|
| 295 |
-} |
|
| 296 |
- |
|
| 297 |
-func (ep *endpoint) SetValue(value []byte) error {
|
|
| 298 |
- return json.Unmarshal(value, ep) |
|
| 299 |
-} |
|
| 300 |
- |
|
| 301 |
-func (ep *endpoint) MarshalJSON() ([]byte, error) {
|
|
| 302 |
- epMap := make(map[string]interface{})
|
|
| 303 |
- |
|
| 304 |
- epMap["id"] = ep.id |
|
| 305 |
- epMap["nid"] = ep.nid |
|
| 306 |
- epMap["remote"] = ep.remote |
|
| 307 |
- if ep.profileId != "" {
|
|
| 308 |
- epMap["profileId"] = ep.profileId |
|
| 309 |
- } |
|
| 310 |
- |
|
| 311 |
- if ep.addr != nil {
|
|
| 312 |
- epMap["addr"] = ep.addr.String() |
|
| 313 |
- } |
|
| 314 |
- if len(ep.mac) != 0 {
|
|
| 315 |
- epMap["mac"] = ep.mac.String() |
|
| 316 |
- } |
|
| 317 |
- |
|
| 318 |
- return json.Marshal(epMap) |
|
| 319 |
-} |
|
| 320 |
- |
|
| 321 |
-func (ep *endpoint) UnmarshalJSON(value []byte) error {
|
|
| 322 |
- var ( |
|
| 323 |
- err error |
|
| 324 |
- epMap map[string]interface{}
|
|
| 325 |
- ) |
|
| 326 |
- |
|
| 327 |
- json.Unmarshal(value, &epMap) |
|
| 328 |
- |
|
| 329 |
- ep.id = epMap["id"].(string) |
|
| 330 |
- ep.nid = epMap["nid"].(string) |
|
| 331 |
- ep.remote = epMap["remote"].(bool) |
|
| 332 |
- if v, ok := epMap["profileId"]; ok {
|
|
| 333 |
- ep.profileId = v.(string) |
|
| 334 |
- } |
|
| 335 |
- if v, ok := epMap["mac"]; ok {
|
|
| 336 |
- if ep.mac, err = net.ParseMAC(v.(string)); err != nil {
|
|
| 337 |
- return types.InternalErrorf("failed to decode endpoint interface mac address after json unmarshal: %s", v.(string))
|
|
| 338 |
- } |
|
| 339 |
- } |
|
| 340 |
- if v, ok := epMap["addr"]; ok {
|
|
| 341 |
- if ep.addr, err = types.ParseCIDR(v.(string)); err != nil {
|
|
| 342 |
- return types.InternalErrorf("failed to decode endpoint interface ipv4 address after json unmarshal: %v", err)
|
|
| 343 |
- } |
|
| 344 |
- } |
|
| 345 |
- return nil |
|
| 346 |
-} |
| 347 | 226 |
deleted file mode 100644 |
| ... | ... |
@@ -1,209 +0,0 @@ |
| 1 |
-package overlay |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "encoding/json" |
|
| 5 |
- "fmt" |
|
| 6 |
- "sync" |
|
| 7 |
- |
|
| 8 |
- "github.com/Microsoft/hcsshim" |
|
| 9 |
- "github.com/Sirupsen/logrus" |
|
| 10 |
- "github.com/docker/libnetwork/datastore" |
|
| 11 |
-) |
|
| 12 |
- |
|
| 13 |
-const overlayNetworkPrefix = "overlay/network" |
|
| 14 |
- |
|
| 15 |
-type localNetwork struct {
|
|
| 16 |
- id string |
|
| 17 |
- hnsID string |
|
| 18 |
- providerAddress string |
|
| 19 |
- dbIndex uint64 |
|
| 20 |
- dbExists bool |
|
| 21 |
- sync.Mutex |
|
| 22 |
-} |
|
| 23 |
- |
|
| 24 |
-func (d *driver) findHnsNetwork(n *network) error {
|
|
| 25 |
- ln, err := d.getLocalNetworkFromStore(n.id) |
|
| 26 |
- |
|
| 27 |
- if err != nil {
|
|
| 28 |
- return err |
|
| 29 |
- } |
|
| 30 |
- |
|
| 31 |
- if ln == nil {
|
|
| 32 |
- subnets := []hcsshim.Subnet{}
|
|
| 33 |
- |
|
| 34 |
- for _, s := range n.subnets {
|
|
| 35 |
- subnet := hcsshim.Subnet{
|
|
| 36 |
- AddressPrefix: s.subnetIP.String(), |
|
| 37 |
- } |
|
| 38 |
- |
|
| 39 |
- if s.gwIP != nil {
|
|
| 40 |
- subnet.GatewayAddress = s.gwIP.IP.String() |
|
| 41 |
- } |
|
| 42 |
- |
|
| 43 |
- vsidPolicy, err := json.Marshal(hcsshim.VsidPolicy{
|
|
| 44 |
- Type: "VSID", |
|
| 45 |
- VSID: uint(s.vni), |
|
| 46 |
- }) |
|
| 47 |
- |
|
| 48 |
- if err != nil {
|
|
| 49 |
- return err |
|
| 50 |
- } |
|
| 51 |
- |
|
| 52 |
- subnet.Policies = append(subnet.Policies, vsidPolicy) |
|
| 53 |
- subnets = append(subnets, subnet) |
|
| 54 |
- } |
|
| 55 |
- |
|
| 56 |
- network := &hcsshim.HNSNetwork{
|
|
| 57 |
- Name: n.name, |
|
| 58 |
- Type: d.Type(), |
|
| 59 |
- Subnets: subnets, |
|
| 60 |
- NetworkAdapterName: n.interfaceName, |
|
| 61 |
- } |
|
| 62 |
- |
|
| 63 |
- configurationb, err := json.Marshal(network) |
|
| 64 |
- if err != nil {
|
|
| 65 |
- return err |
|
| 66 |
- } |
|
| 67 |
- |
|
| 68 |
- configuration := string(configurationb) |
|
| 69 |
- logrus.Infof("HNSNetwork Request =%v", configuration)
|
|
| 70 |
- |
|
| 71 |
- hnsresponse, err := hcsshim.HNSNetworkRequest("POST", "", configuration)
|
|
| 72 |
- if err != nil {
|
|
| 73 |
- return err |
|
| 74 |
- } |
|
| 75 |
- |
|
| 76 |
- n.hnsId = hnsresponse.Id |
|
| 77 |
- n.providerAddress = hnsresponse.ManagementIP |
|
| 78 |
- |
|
| 79 |
- // Save local host specific info |
|
| 80 |
- if err := d.writeLocalNetworkToStore(n); err != nil {
|
|
| 81 |
- return fmt.Errorf("failed to update data store for network %v: %v", n.id, err)
|
|
| 82 |
- } |
|
| 83 |
- } else {
|
|
| 84 |
- n.hnsId = ln.hnsID |
|
| 85 |
- n.providerAddress = ln.providerAddress |
|
| 86 |
- } |
|
| 87 |
- |
|
| 88 |
- return nil |
|
| 89 |
-} |
|
| 90 |
- |
|
| 91 |
-func (d *driver) getLocalNetworkFromStore(nid string) (*localNetwork, error) {
|
|
| 92 |
- |
|
| 93 |
- if d.localStore == nil {
|
|
| 94 |
- return nil, fmt.Errorf("overlay local store not initialized, network not found")
|
|
| 95 |
- } |
|
| 96 |
- |
|
| 97 |
- n := &localNetwork{id: nid}
|
|
| 98 |
- if err := d.localStore.GetObject(datastore.Key(n.Key()...), n); err != nil {
|
|
| 99 |
- return nil, nil |
|
| 100 |
- } |
|
| 101 |
- |
|
| 102 |
- return n, nil |
|
| 103 |
-} |
|
| 104 |
- |
|
| 105 |
-func (d *driver) deleteLocalNetworkFromStore(n *network) error {
|
|
| 106 |
- if d.localStore == nil {
|
|
| 107 |
- return fmt.Errorf("overlay local store not initialized, network not deleted")
|
|
| 108 |
- } |
|
| 109 |
- |
|
| 110 |
- ln, err := d.getLocalNetworkFromStore(n.id) |
|
| 111 |
- |
|
| 112 |
- if err != nil {
|
|
| 113 |
- return err |
|
| 114 |
- } |
|
| 115 |
- |
|
| 116 |
- if err = d.localStore.DeleteObjectAtomic(ln); err != nil {
|
|
| 117 |
- return err |
|
| 118 |
- } |
|
| 119 |
- |
|
| 120 |
- return nil |
|
| 121 |
-} |
|
| 122 |
- |
|
| 123 |
-func (d *driver) writeLocalNetworkToStore(n *network) error {
|
|
| 124 |
- if d.localStore == nil {
|
|
| 125 |
- return fmt.Errorf("overlay local store not initialized, network not added")
|
|
| 126 |
- } |
|
| 127 |
- |
|
| 128 |
- ln := &localNetwork{
|
|
| 129 |
- id: n.id, |
|
| 130 |
- hnsID: n.hnsId, |
|
| 131 |
- providerAddress: n.providerAddress, |
|
| 132 |
- } |
|
| 133 |
- |
|
| 134 |
- if err := d.localStore.PutObjectAtomic(ln); err != nil {
|
|
| 135 |
- return err |
|
| 136 |
- } |
|
| 137 |
- return nil |
|
| 138 |
-} |
|
| 139 |
- |
|
| 140 |
-func (n *localNetwork) DataScope() string {
|
|
| 141 |
- return datastore.LocalScope |
|
| 142 |
-} |
|
| 143 |
- |
|
| 144 |
-func (n *localNetwork) New() datastore.KVObject {
|
|
| 145 |
- return &localNetwork{}
|
|
| 146 |
-} |
|
| 147 |
- |
|
| 148 |
-func (n *localNetwork) CopyTo(o datastore.KVObject) error {
|
|
| 149 |
- dstep := o.(*localNetwork) |
|
| 150 |
- *dstep = *n |
|
| 151 |
- return nil |
|
| 152 |
-} |
|
| 153 |
- |
|
| 154 |
-func (n *localNetwork) Key() []string {
|
|
| 155 |
- return []string{overlayNetworkPrefix, n.id}
|
|
| 156 |
-} |
|
| 157 |
- |
|
| 158 |
-func (n *localNetwork) KeyPrefix() []string {
|
|
| 159 |
- return []string{overlayNetworkPrefix}
|
|
| 160 |
-} |
|
| 161 |
- |
|
| 162 |
-func (n *localNetwork) Index() uint64 {
|
|
| 163 |
- return n.dbIndex |
|
| 164 |
-} |
|
| 165 |
- |
|
| 166 |
-func (n *localNetwork) SetIndex(index uint64) {
|
|
| 167 |
- n.dbIndex = index |
|
| 168 |
- n.dbExists = true |
|
| 169 |
-} |
|
| 170 |
- |
|
| 171 |
-func (n *localNetwork) Exists() bool {
|
|
| 172 |
- return n.dbExists |
|
| 173 |
-} |
|
| 174 |
- |
|
| 175 |
-func (n *localNetwork) Skip() bool {
|
|
| 176 |
- return false |
|
| 177 |
-} |
|
| 178 |
- |
|
| 179 |
-func (n *localNetwork) Value() []byte {
|
|
| 180 |
- b, err := json.Marshal(n) |
|
| 181 |
- if err != nil {
|
|
| 182 |
- return nil |
|
| 183 |
- } |
|
| 184 |
- return b |
|
| 185 |
-} |
|
| 186 |
- |
|
| 187 |
-func (n *localNetwork) SetValue(value []byte) error {
|
|
| 188 |
- return json.Unmarshal(value, n) |
|
| 189 |
-} |
|
| 190 |
- |
|
| 191 |
-func (n *localNetwork) MarshalJSON() ([]byte, error) {
|
|
| 192 |
- networkMap := make(map[string]interface{})
|
|
| 193 |
- |
|
| 194 |
- networkMap["id"] = n.id |
|
| 195 |
- networkMap["hnsID"] = n.hnsID |
|
| 196 |
- networkMap["providerAddress"] = n.providerAddress |
|
| 197 |
- return json.Marshal(networkMap) |
|
| 198 |
-} |
|
| 199 |
- |
|
| 200 |
-func (n *localNetwork) UnmarshalJSON(value []byte) error {
|
|
| 201 |
- var networkMap map[string]interface{}
|
|
| 202 |
- |
|
| 203 |
- json.Unmarshal(value, &networkMap) |
|
| 204 |
- |
|
| 205 |
- n.id = networkMap["id"].(string) |
|
| 206 |
- n.hnsID = networkMap["hnsID"].(string) |
|
| 207 |
- n.providerAddress = networkMap["providerAddress"].(string) |
|
| 208 |
- return nil |
|
| 209 |
-} |
| ... | ... |
@@ -10,7 +10,6 @@ import ( |
| 10 | 10 |
|
| 11 | 11 |
"github.com/Microsoft/hcsshim" |
| 12 | 12 |
"github.com/Sirupsen/logrus" |
| 13 |
- "github.com/docker/libnetwork/datastore" |
|
| 14 | 13 |
"github.com/docker/libnetwork/driverapi" |
| 15 | 14 |
"github.com/docker/libnetwork/netlabel" |
| 16 | 15 |
"github.com/docker/libnetwork/types" |
| ... | ... |
@@ -25,9 +24,8 @@ type networkTable map[string]*network |
| 25 | 25 |
|
| 26 | 26 |
type subnet struct {
|
| 27 | 27 |
vni uint32 |
| 28 |
- initErr error |
|
| 29 | 28 |
subnetIP *net.IPNet |
| 30 |
- gwIP *net.IPNet |
|
| 29 |
+ gwIP *net.IP |
|
| 31 | 30 |
} |
| 32 | 31 |
|
| 33 | 32 |
type subnetJSON struct {
|
| ... | ... |
@@ -40,8 +38,6 @@ type network struct {
|
| 40 | 40 |
id string |
| 41 | 41 |
name string |
| 42 | 42 |
hnsId string |
| 43 |
- dbIndex uint64 |
|
| 44 |
- dbExists bool |
|
| 45 | 43 |
providerAddress string |
| 46 | 44 |
interfaceName string |
| 47 | 45 |
endpoints endpointTable |
| ... | ... |
@@ -65,22 +61,31 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d
|
| 65 | 65 |
var ( |
| 66 | 66 |
networkName string |
| 67 | 67 |
interfaceName string |
| 68 |
+ staleNetworks []string |
|
| 68 | 69 |
) |
| 69 | 70 |
|
| 70 | 71 |
if id == "" {
|
| 71 | 72 |
return fmt.Errorf("invalid network id")
|
| 72 | 73 |
} |
| 73 | 74 |
|
| 75 |
+ if nInfo == nil {
|
|
| 76 |
+ return fmt.Errorf("invalid network info structure")
|
|
| 77 |
+ } |
|
| 78 |
+ |
|
| 74 | 79 |
if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" {
|
| 75 | 80 |
return types.BadRequestErrorf("ipv4 pool is empty")
|
| 76 | 81 |
} |
| 77 | 82 |
|
| 83 |
+ staleNetworks = make([]string, 0) |
|
| 78 | 84 |
vnis := make([]uint32, 0, len(ipV4Data)) |
| 79 | 85 |
|
| 80 |
- // Since we perform lazy configuration make sure we try |
|
| 81 |
- // configuring the driver when we enter CreateNetwork |
|
| 82 |
- if err := d.configure(); err != nil {
|
|
| 83 |
- return err |
|
| 86 |
+ existingNetwork := d.network(id) |
|
| 87 |
+ if existingNetwork != nil {
|
|
| 88 |
+ logrus.Debugf("Network preexists. Deleting %s", id)
|
|
| 89 |
+ err := d.DeleteNetwork(id) |
|
| 90 |
+ if err != nil {
|
|
| 91 |
+ logrus.Errorf("Error deleting stale network %s", err.Error())
|
|
| 92 |
+ } |
|
| 84 | 93 |
} |
| 85 | 94 |
|
| 86 | 95 |
n := &network{
|
| ... | ... |
@@ -119,23 +124,43 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d
|
| 119 | 119 |
|
| 120 | 120 |
// If we are getting vnis from libnetwork, either we get for |
| 121 | 121 |
// all subnets or none. |
| 122 |
- if len(vnis) != 0 && len(vnis) < len(ipV4Data) {
|
|
| 123 |
- return fmt.Errorf("insufficient vnis(%d) passed to overlay", len(vnis))
|
|
| 122 |
+ if len(vnis) < len(ipV4Data) {
|
|
| 123 |
+ return fmt.Errorf("insufficient vnis(%d) passed to overlay. Windows driver requires VNIs to be prepopulated", len(vnis))
|
|
| 124 | 124 |
} |
| 125 | 125 |
|
| 126 | 126 |
for i, ipd := range ipV4Data {
|
| 127 | 127 |
s := &subnet{
|
| 128 | 128 |
subnetIP: ipd.Pool, |
| 129 |
- gwIP: ipd.Gateway, |
|
| 129 |
+ gwIP: &ipd.Gateway.IP, |
|
| 130 | 130 |
} |
| 131 | 131 |
|
| 132 | 132 |
if len(vnis) != 0 {
|
| 133 | 133 |
s.vni = vnis[i] |
| 134 | 134 |
} |
| 135 | 135 |
|
| 136 |
+ d.Lock() |
|
| 137 |
+ for _, network := range d.networks {
|
|
| 138 |
+ found := false |
|
| 139 |
+ for _, sub := range network.subnets {
|
|
| 140 |
+ if sub.vni == s.vni {
|
|
| 141 |
+ staleNetworks = append(staleNetworks, network.id) |
|
| 142 |
+ found = true |
|
| 143 |
+ break |
|
| 144 |
+ } |
|
| 145 |
+ } |
|
| 146 |
+ if found {
|
|
| 147 |
+ break |
|
| 148 |
+ } |
|
| 149 |
+ } |
|
| 150 |
+ d.Unlock() |
|
| 151 |
+ |
|
| 136 | 152 |
n.subnets = append(n.subnets, s) |
| 137 | 153 |
} |
| 138 | 154 |
|
| 155 |
+ for _, staleNetwork := range staleNetworks {
|
|
| 156 |
+ d.DeleteNetwork(staleNetwork) |
|
| 157 |
+ } |
|
| 158 |
+ |
|
| 139 | 159 |
n.name = networkName |
| 140 | 160 |
if n.name == "" {
|
| 141 | 161 |
n.name = id |
| ... | ... |
@@ -143,10 +168,6 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d
|
| 143 | 143 |
|
| 144 | 144 |
n.interfaceName = interfaceName |
| 145 | 145 |
|
| 146 |
- if err := n.writeToStore(); err != nil {
|
|
| 147 |
- return fmt.Errorf("failed to update data store for network %v: %v", n.id, err)
|
|
| 148 |
- } |
|
| 149 |
- |
|
| 150 | 146 |
if nInfo != nil {
|
| 151 | 147 |
if err := nInfo.TableEventRegister(ovPeerTable); err != nil {
|
| 152 | 148 |
return err |
| ... | ... |
@@ -155,8 +176,13 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d
|
| 155 | 155 |
|
| 156 | 156 |
d.addNetwork(n) |
| 157 | 157 |
|
| 158 |
- err := d.findHnsNetwork(n) |
|
| 159 |
- genData["com.docker.network.windowsshim.hnsid"] = n.hnsId |
|
| 158 |
+ err := d.createHnsNetwork(n) |
|
| 159 |
+ |
|
| 160 |
+ if err != nil {
|
|
| 161 |
+ d.deleteNetwork(id) |
|
| 162 |
+ } else {
|
|
| 163 |
+ genData["com.docker.network.windowsshim.hnsid"] = n.hnsId |
|
| 164 |
+ } |
|
| 160 | 165 |
|
| 161 | 166 |
return err |
| 162 | 167 |
} |
| ... | ... |
@@ -166,23 +192,17 @@ func (d *driver) DeleteNetwork(nid string) error {
|
| 166 | 166 |
return fmt.Errorf("invalid network id")
|
| 167 | 167 |
} |
| 168 | 168 |
|
| 169 |
- // Make sure driver resources are initialized before proceeding |
|
| 170 |
- if err := d.configure(); err != nil {
|
|
| 171 |
- return err |
|
| 172 |
- } |
|
| 173 |
- |
|
| 174 | 169 |
n := d.network(nid) |
| 175 | 170 |
if n == nil {
|
| 176 |
- return fmt.Errorf("could not find network with id %s", nid)
|
|
| 171 |
+ return types.ForbiddenErrorf("could not find network with id %s", nid)
|
|
| 177 | 172 |
} |
| 178 | 173 |
|
| 179 | 174 |
_, err := hcsshim.HNSNetworkRequest("DELETE", n.hnsId, "")
|
| 180 | 175 |
if err != nil {
|
| 181 |
- return err |
|
| 176 |
+ return types.ForbiddenErrorf(err.Error()) |
|
| 182 | 177 |
} |
| 183 | 178 |
|
| 184 | 179 |
d.deleteNetwork(nid) |
| 185 |
- d.deleteLocalNetworkFromStore(n) |
|
| 186 | 180 |
|
| 187 | 181 |
return nil |
| 188 | 182 |
} |
| ... | ... |
@@ -209,259 +229,107 @@ func (d *driver) deleteNetwork(nid string) {
|
| 209 | 209 |
|
| 210 | 210 |
func (d *driver) network(nid string) *network {
|
| 211 | 211 |
d.Lock() |
| 212 |
- networks := d.networks |
|
| 213 |
- d.Unlock() |
|
| 214 |
- |
|
| 215 |
- n, ok := networks[nid] |
|
| 216 |
- if !ok {
|
|
| 217 |
- n = d.getNetworkFromStore(nid) |
|
| 218 |
- if n != nil {
|
|
| 219 |
- n.driver = d |
|
| 220 |
- n.endpoints = endpointTable{}
|
|
| 221 |
- networks[nid] = n |
|
| 222 |
- } |
|
| 223 |
- } |
|
| 224 |
- |
|
| 225 |
- return n |
|
| 212 |
+ defer d.Unlock() |
|
| 213 |
+ return d.networks[nid] |
|
| 226 | 214 |
} |
| 227 | 215 |
|
| 228 |
-func (d *driver) getNetworkFromStore(nid string) *network {
|
|
| 229 |
- if d.store == nil {
|
|
| 230 |
- return nil |
|
| 231 |
- } |
|
| 232 |
- |
|
| 233 |
- n := &network{id: nid}
|
|
| 234 |
- if err := d.store.GetObject(datastore.Key(n.Key()...), n); err != nil {
|
|
| 235 |
- return nil |
|
| 236 |
- } |
|
| 237 |
- |
|
| 238 |
- // As the network is being discovered from the global store, HNS may not be aware of it yet |
|
| 239 |
- err := d.findHnsNetwork(n) |
|
| 240 |
- if err != nil {
|
|
| 241 |
- logrus.Errorf("Failed to find hns network: %v", err)
|
|
| 242 |
- return nil |
|
| 243 |
- } |
|
| 216 |
+// func (n *network) restoreNetworkEndpoints() error {
|
|
| 217 |
+// logrus.Infof("Restoring endpoints for overlay network: %s", n.id)
|
|
| 244 | 218 |
|
| 245 |
- return n |
|
| 246 |
-} |
|
| 219 |
+// hnsresponse, err := hcsshim.HNSListEndpointRequest("GET", "", "")
|
|
| 220 |
+// if err != nil {
|
|
| 221 |
+// return err |
|
| 222 |
+// } |
|
| 247 | 223 |
|
| 248 |
-func (n *network) vxlanID(s *subnet) uint32 {
|
|
| 249 |
- n.Lock() |
|
| 250 |
- defer n.Unlock() |
|
| 224 |
+// for _, endpoint := range hnsresponse {
|
|
| 225 |
+// if endpoint.VirtualNetwork != n.hnsId {
|
|
| 226 |
+// continue |
|
| 227 |
+// } |
|
| 251 | 228 |
|
| 252 |
- return s.vni |
|
| 253 |
-} |
|
| 229 |
+// ep := n.convertToOverlayEndpoint(&endpoint) |
|
| 254 | 230 |
|
| 255 |
-func (n *network) setVxlanID(s *subnet, vni uint32) {
|
|
| 256 |
- n.Lock() |
|
| 257 |
- s.vni = vni |
|
| 258 |
- n.Unlock() |
|
| 259 |
-} |
|
| 231 |
+// if ep != nil {
|
|
| 232 |
+// logrus.Debugf("Restored endpoint:%s Remote:%t", ep.id, ep.remote)
|
|
| 233 |
+// n.addEndpoint(ep) |
|
| 234 |
+// } |
|
| 235 |
+// } |
|
| 260 | 236 |
|
| 261 |
-func (n *network) Key() []string {
|
|
| 262 |
- return []string{"overlay", "network", n.id}
|
|
| 263 |
-} |
|
| 264 |
- |
|
| 265 |
-func (n *network) KeyPrefix() []string {
|
|
| 266 |
- return []string{"overlay", "network"}
|
|
| 267 |
-} |
|
| 237 |
+// return nil |
|
| 238 |
+// } |
|
| 268 | 239 |
|
| 269 |
-func (n *network) Value() []byte {
|
|
| 270 |
- m := map[string]interface{}{}
|
|
| 271 |
- |
|
| 272 |
- netJSON := []*subnetJSON{}
|
|
| 273 |
- |
|
| 274 |
- for _, s := range n.subnets {
|
|
| 275 |
- sj := &subnetJSON{
|
|
| 276 |
- SubnetIP: s.subnetIP.String(), |
|
| 277 |
- GwIP: s.gwIP.String(), |
|
| 278 |
- Vni: s.vni, |
|
| 279 |
- } |
|
| 280 |
- netJSON = append(netJSON, sj) |
|
| 240 |
+func (n *network) convertToOverlayEndpoint(v *hcsshim.HNSEndpoint) *endpoint {
|
|
| 241 |
+ ep := &endpoint{
|
|
| 242 |
+ id: v.Name, |
|
| 243 |
+ profileId: v.Id, |
|
| 244 |
+ nid: n.id, |
|
| 245 |
+ remote: v.IsRemoteEndpoint, |
|
| 281 | 246 |
} |
| 282 | 247 |
|
| 283 |
- b, err := json.Marshal(netJSON) |
|
| 284 |
- if err != nil {
|
|
| 285 |
- return []byte{}
|
|
| 286 |
- } |
|
| 248 |
+ mac, err := net.ParseMAC(v.MacAddress) |
|
| 287 | 249 |
|
| 288 |
- m["secure"] = n.secure |
|
| 289 |
- m["subnets"] = netJSON |
|
| 290 |
- m["interfaceName"] = n.interfaceName |
|
| 291 |
- m["providerAddress"] = n.providerAddress |
|
| 292 |
- m["hnsId"] = n.hnsId |
|
| 293 |
- m["name"] = n.name |
|
| 294 |
- b, err = json.Marshal(m) |
|
| 295 | 250 |
if err != nil {
|
| 296 |
- return []byte{}
|
|
| 251 |
+ return nil |
|
| 297 | 252 |
} |
| 298 | 253 |
|
| 299 |
- return b |
|
| 300 |
-} |
|
| 301 |
- |
|
| 302 |
-func (n *network) Index() uint64 {
|
|
| 303 |
- return n.dbIndex |
|
| 304 |
-} |
|
| 254 |
+ ep.mac = mac |
|
| 255 |
+ ep.addr = &net.IPNet{
|
|
| 256 |
+ IP: v.IPAddress, |
|
| 257 |
+ Mask: net.CIDRMask(32, 32), |
|
| 258 |
+ } |
|
| 305 | 259 |
|
| 306 |
-func (n *network) SetIndex(index uint64) {
|
|
| 307 |
- n.dbIndex = index |
|
| 308 |
- n.dbExists = true |
|
| 260 |
+ return ep |
|
| 309 | 261 |
} |
| 310 | 262 |
|
| 311 |
-func (n *network) Exists() bool {
|
|
| 312 |
- return n.dbExists |
|
| 313 |
-} |
|
| 263 |
+func (d *driver) createHnsNetwork(n *network) error {
|
|
| 314 | 264 |
|
| 315 |
-func (n *network) Skip() bool {
|
|
| 316 |
- return false |
|
| 317 |
-} |
|
| 265 |
+ subnets := []hcsshim.Subnet{}
|
|
| 318 | 266 |
|
| 319 |
-func (n *network) SetValue(value []byte) error {
|
|
| 320 |
- var ( |
|
| 321 |
- m map[string]interface{}
|
|
| 322 |
- newNet bool |
|
| 323 |
- isMap = true |
|
| 324 |
- netJSON = []*subnetJSON{}
|
|
| 325 |
- ) |
|
| 267 |
+ for _, s := range n.subnets {
|
|
| 268 |
+ subnet := hcsshim.Subnet{
|
|
| 269 |
+ AddressPrefix: s.subnetIP.String(), |
|
| 270 |
+ } |
|
| 326 | 271 |
|
| 327 |
- if err := json.Unmarshal(value, &m); err != nil {
|
|
| 328 |
- err := json.Unmarshal(value, &netJSON) |
|
| 329 |
- if err != nil {
|
|
| 330 |
- return err |
|
| 272 |
+ if s.gwIP != nil {
|
|
| 273 |
+ subnet.GatewayAddress = s.gwIP.String() |
|
| 331 | 274 |
} |
| 332 |
- isMap = false |
|
| 333 |
- } |
|
| 334 | 275 |
|
| 335 |
- if len(n.subnets) == 0 {
|
|
| 336 |
- newNet = true |
|
| 337 |
- } |
|
| 276 |
+ vsidPolicy, err := json.Marshal(hcsshim.VsidPolicy{
|
|
| 277 |
+ Type: "VSID", |
|
| 278 |
+ VSID: uint(s.vni), |
|
| 279 |
+ }) |
|
| 338 | 280 |
|
| 339 |
- if isMap {
|
|
| 340 |
- if val, ok := m["secure"]; ok {
|
|
| 341 |
- n.secure = val.(bool) |
|
| 342 |
- } |
|
| 343 |
- if val, ok := m["providerAddress"]; ok {
|
|
| 344 |
- n.providerAddress = val.(string) |
|
| 345 |
- } |
|
| 346 |
- if val, ok := m["interfaceName"]; ok {
|
|
| 347 |
- n.interfaceName = val.(string) |
|
| 348 |
- } |
|
| 349 |
- if val, ok := m["hnsId"]; ok {
|
|
| 350 |
- n.hnsId = val.(string) |
|
| 351 |
- } |
|
| 352 |
- if val, ok := m["name"]; ok {
|
|
| 353 |
- n.name = val.(string) |
|
| 354 |
- } |
|
| 355 |
- bytes, err := json.Marshal(m["subnets"]) |
|
| 356 | 281 |
if err != nil {
|
| 357 | 282 |
return err |
| 358 | 283 |
} |
| 359 |
- if err := json.Unmarshal(bytes, &netJSON); err != nil {
|
|
| 360 |
- return err |
|
| 361 |
- } |
|
| 362 |
- } |
|
| 363 |
- |
|
| 364 |
- for _, sj := range netJSON {
|
|
| 365 |
- subnetIPstr := sj.SubnetIP |
|
| 366 |
- gwIPstr := sj.GwIP |
|
| 367 |
- vni := sj.Vni |
|
| 368 | 284 |
|
| 369 |
- subnetIP, _ := types.ParseCIDR(subnetIPstr) |
|
| 370 |
- gwIP, _ := types.ParseCIDR(gwIPstr) |
|
| 371 |
- |
|
| 372 |
- if newNet {
|
|
| 373 |
- s := &subnet{
|
|
| 374 |
- subnetIP: subnetIP, |
|
| 375 |
- gwIP: gwIP, |
|
| 376 |
- vni: vni, |
|
| 377 |
- } |
|
| 378 |
- n.subnets = append(n.subnets, s) |
|
| 379 |
- } else {
|
|
| 380 |
- sNet := n.getMatchingSubnet(subnetIP) |
|
| 381 |
- if sNet != nil {
|
|
| 382 |
- sNet.vni = vni |
|
| 383 |
- } |
|
| 384 |
- } |
|
| 285 |
+ subnet.Policies = append(subnet.Policies, vsidPolicy) |
|
| 286 |
+ subnets = append(subnets, subnet) |
|
| 385 | 287 |
} |
| 386 |
- return nil |
|
| 387 |
-} |
|
| 388 | 288 |
|
| 389 |
-func (n *network) DataScope() string {
|
|
| 390 |
- return datastore.GlobalScope |
|
| 391 |
-} |
|
| 392 |
- |
|
| 393 |
-func (n *network) writeToStore() error {
|
|
| 394 |
- if n.driver.store == nil {
|
|
| 395 |
- return nil |
|
| 289 |
+ network := &hcsshim.HNSNetwork{
|
|
| 290 |
+ Name: n.name, |
|
| 291 |
+ Type: d.Type(), |
|
| 292 |
+ Subnets: subnets, |
|
| 293 |
+ NetworkAdapterName: n.interfaceName, |
|
| 396 | 294 |
} |
| 397 | 295 |
|
| 398 |
- return n.driver.store.PutObjectAtomic(n) |
|
| 399 |
-} |
|
| 400 |
- |
|
| 401 |
-func (n *network) releaseVxlanID() ([]uint32, error) {
|
|
| 402 |
- if len(n.subnets) == 0 {
|
|
| 403 |
- return nil, nil |
|
| 404 |
- } |
|
| 405 |
- |
|
| 406 |
- if n.driver.store != nil {
|
|
| 407 |
- if err := n.driver.store.DeleteObjectAtomic(n); err != nil {
|
|
| 408 |
- if err == datastore.ErrKeyModified || err == datastore.ErrKeyNotFound {
|
|
| 409 |
- // In both the above cases we can safely assume that the key has been removed by some other |
|
| 410 |
- // instance and so simply get out of here |
|
| 411 |
- return nil, nil |
|
| 412 |
- } |
|
| 413 |
- |
|
| 414 |
- return nil, fmt.Errorf("failed to delete network to vxlan id map: %v", err)
|
|
| 415 |
- } |
|
| 416 |
- } |
|
| 417 |
- var vnis []uint32 |
|
| 418 |
- for _, s := range n.subnets {
|
|
| 419 |
- if n.driver.vxlanIdm != nil {
|
|
| 420 |
- vni := n.vxlanID(s) |
|
| 421 |
- vnis = append(vnis, vni) |
|
| 422 |
- n.driver.vxlanIdm.Release(uint64(vni)) |
|
| 423 |
- } |
|
| 424 |
- |
|
| 425 |
- n.setVxlanID(s, 0) |
|
| 296 |
+ configurationb, err := json.Marshal(network) |
|
| 297 |
+ if err != nil {
|
|
| 298 |
+ return err |
|
| 426 | 299 |
} |
| 427 | 300 |
|
| 428 |
- return vnis, nil |
|
| 429 |
-} |
|
| 301 |
+ configuration := string(configurationb) |
|
| 302 |
+ logrus.Infof("HNSNetwork Request =%v", configuration)
|
|
| 430 | 303 |
|
| 431 |
-func (n *network) obtainVxlanID(s *subnet) error {
|
|
| 432 |
- //return if the subnet already has a vxlan id assigned |
|
| 433 |
- if s.vni != 0 {
|
|
| 434 |
- return nil |
|
| 435 |
- } |
|
| 436 |
- |
|
| 437 |
- if n.driver.store == nil {
|
|
| 438 |
- return fmt.Errorf("no valid vxlan id and no datastore configured, cannot obtain vxlan id")
|
|
| 304 |
+ hnsresponse, err := hcsshim.HNSNetworkRequest("POST", "", configuration)
|
|
| 305 |
+ if err != nil {
|
|
| 306 |
+ return err |
|
| 439 | 307 |
} |
| 440 | 308 |
|
| 441 |
- for {
|
|
| 442 |
- if err := n.driver.store.GetObject(datastore.Key(n.Key()...), n); err != nil {
|
|
| 443 |
- return fmt.Errorf("getting network %q from datastore failed %v", n.id, err)
|
|
| 444 |
- } |
|
| 445 |
- |
|
| 446 |
- if s.vni == 0 {
|
|
| 447 |
- vxlanID, err := n.driver.vxlanIdm.GetID() |
|
| 448 |
- if err != nil {
|
|
| 449 |
- return fmt.Errorf("failed to allocate vxlan id: %v", err)
|
|
| 450 |
- } |
|
| 309 |
+ n.hnsId = hnsresponse.Id |
|
| 310 |
+ n.providerAddress = hnsresponse.ManagementIP |
|
| 451 | 311 |
|
| 452 |
- n.setVxlanID(s, uint32(vxlanID)) |
|
| 453 |
- if err := n.writeToStore(); err != nil {
|
|
| 454 |
- n.driver.vxlanIdm.Release(uint64(n.vxlanID(s))) |
|
| 455 |
- n.setVxlanID(s, 0) |
|
| 456 |
- if err == datastore.ErrKeyModified {
|
|
| 457 |
- continue |
|
| 458 |
- } |
|
| 459 |
- return fmt.Errorf("network %q failed to update data store: %v", n.id, err)
|
|
| 460 |
- } |
|
| 461 |
- return nil |
|
| 462 |
- } |
|
| 463 |
- return nil |
|
| 464 |
- } |
|
| 312 |
+ return nil |
|
| 465 | 313 |
} |
| 466 | 314 |
|
| 467 | 315 |
// contains return true if the passed ip belongs to one the network's |
| 468 | 316 |
deleted file mode 100644 |
| ... | ... |
@@ -1,179 +0,0 @@ |
| 1 |
-package overlay |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "net" |
|
| 6 |
- "strings" |
|
| 7 |
- "time" |
|
| 8 |
- |
|
| 9 |
- "github.com/Sirupsen/logrus" |
|
| 10 |
- "github.com/hashicorp/serf/serf" |
|
| 11 |
-) |
|
| 12 |
- |
|
| 13 |
-type ovNotify struct {
|
|
| 14 |
- action string |
|
| 15 |
- ep *endpoint |
|
| 16 |
- nw *network |
|
| 17 |
-} |
|
| 18 |
- |
|
| 19 |
-type logWriter struct{}
|
|
| 20 |
- |
|
| 21 |
-func (l *logWriter) Write(p []byte) (int, error) {
|
|
| 22 |
- str := string(p) |
|
| 23 |
- |
|
| 24 |
- switch {
|
|
| 25 |
- case strings.Contains(str, "[WARN]"): |
|
| 26 |
- logrus.Warn(str) |
|
| 27 |
- case strings.Contains(str, "[DEBUG]"): |
|
| 28 |
- logrus.Debug(str) |
|
| 29 |
- case strings.Contains(str, "[INFO]"): |
|
| 30 |
- logrus.Info(str) |
|
| 31 |
- case strings.Contains(str, "[ERR]"): |
|
| 32 |
- logrus.Error(str) |
|
| 33 |
- } |
|
| 34 |
- |
|
| 35 |
- return len(p), nil |
|
| 36 |
-} |
|
| 37 |
- |
|
| 38 |
-func (d *driver) serfInit() error {
|
|
| 39 |
- var err error |
|
| 40 |
- |
|
| 41 |
- config := serf.DefaultConfig() |
|
| 42 |
- config.Init() |
|
| 43 |
- config.MemberlistConfig.BindAddr = d.bindAddress |
|
| 44 |
- |
|
| 45 |
- d.eventCh = make(chan serf.Event, 4) |
|
| 46 |
- config.EventCh = d.eventCh |
|
| 47 |
- config.UserCoalescePeriod = 1 * time.Second |
|
| 48 |
- config.UserQuiescentPeriod = 50 * time.Millisecond |
|
| 49 |
- |
|
| 50 |
- config.LogOutput = &logWriter{}
|
|
| 51 |
- config.MemberlistConfig.LogOutput = config.LogOutput |
|
| 52 |
- |
|
| 53 |
- s, err := serf.Create(config) |
|
| 54 |
- if err != nil {
|
|
| 55 |
- return fmt.Errorf("failed to create cluster node: %v", err)
|
|
| 56 |
- } |
|
| 57 |
- defer func() {
|
|
| 58 |
- if err != nil {
|
|
| 59 |
- s.Shutdown() |
|
| 60 |
- } |
|
| 61 |
- }() |
|
| 62 |
- |
|
| 63 |
- d.serfInstance = s |
|
| 64 |
- |
|
| 65 |
- d.notifyCh = make(chan ovNotify) |
|
| 66 |
- d.exitCh = make(chan chan struct{})
|
|
| 67 |
- |
|
| 68 |
- go d.startSerfLoop(d.eventCh, d.notifyCh, d.exitCh) |
|
| 69 |
- return nil |
|
| 70 |
-} |
|
| 71 |
- |
|
| 72 |
-func (d *driver) serfJoin(neighIP string) error {
|
|
| 73 |
- if neighIP == "" {
|
|
| 74 |
- return fmt.Errorf("no neighbor to join")
|
|
| 75 |
- } |
|
| 76 |
- if _, err := d.serfInstance.Join([]string{neighIP}, false); err != nil {
|
|
| 77 |
- return fmt.Errorf("Failed to join the cluster at neigh IP %s: %v",
|
|
| 78 |
- neighIP, err) |
|
| 79 |
- } |
|
| 80 |
- return nil |
|
| 81 |
-} |
|
| 82 |
- |
|
| 83 |
-func (d *driver) notifyEvent(event ovNotify) {
|
|
| 84 |
- ep := event.ep |
|
| 85 |
- |
|
| 86 |
- ePayload := fmt.Sprintf("%s %s %s %s", event.action, ep.addr.IP.String(),
|
|
| 87 |
- net.IP(ep.addr.Mask).String(), ep.mac.String()) |
|
| 88 |
- eName := fmt.Sprintf("jl %s %s %s", d.serfInstance.LocalMember().Addr.String(),
|
|
| 89 |
- event.nw.id, ep.id) |
|
| 90 |
- |
|
| 91 |
- if err := d.serfInstance.UserEvent(eName, []byte(ePayload), true); err != nil {
|
|
| 92 |
- logrus.Errorf("Sending user event failed: %v\n", err)
|
|
| 93 |
- } |
|
| 94 |
-} |
|
| 95 |
- |
|
| 96 |
-func (d *driver) processEvent(u serf.UserEvent) {
|
|
| 97 |
- logrus.Debugf("Received user event name:%s, payload:%s\n", u.Name,
|
|
| 98 |
- string(u.Payload)) |
|
| 99 |
- |
|
| 100 |
- var dummy, action, vtepStr, nid, eid, ipStr, maskStr, macStr string |
|
| 101 |
- if _, err := fmt.Sscan(u.Name, &dummy, &vtepStr, &nid, &eid); err != nil {
|
|
| 102 |
- fmt.Printf("Failed to scan name string: %v\n", err)
|
|
| 103 |
- } |
|
| 104 |
- |
|
| 105 |
- if _, err := fmt.Sscan(string(u.Payload), &action, |
|
| 106 |
- &ipStr, &maskStr, &macStr); err != nil {
|
|
| 107 |
- fmt.Printf("Failed to scan value string: %v\n", err)
|
|
| 108 |
- } |
|
| 109 |
- |
|
| 110 |
- logrus.Debugf("Parsed data = %s/%s/%s/%s/%s/%s\n", nid, eid, vtepStr, ipStr, maskStr, macStr)
|
|
| 111 |
- |
|
| 112 |
- mac, err := net.ParseMAC(macStr) |
|
| 113 |
- if err != nil {
|
|
| 114 |
- logrus.Errorf("Failed to parse mac: %v\n", err)
|
|
| 115 |
- } |
|
| 116 |
- |
|
| 117 |
- if d.serfInstance.LocalMember().Addr.String() == vtepStr {
|
|
| 118 |
- return |
|
| 119 |
- } |
|
| 120 |
- |
|
| 121 |
- switch action {
|
|
| 122 |
- case "join": |
|
| 123 |
- if err := d.peerAdd(nid, eid, net.ParseIP(ipStr), net.IPMask(net.ParseIP(maskStr).To4()), mac, |
|
| 124 |
- net.ParseIP(vtepStr), true); err != nil {
|
|
| 125 |
- logrus.Errorf("Peer add failed in the driver: %v\n", err)
|
|
| 126 |
- } |
|
| 127 |
- case "leave": |
|
| 128 |
- if err := d.peerDelete(nid, eid, net.ParseIP(ipStr), net.IPMask(net.ParseIP(maskStr).To4()), mac, |
|
| 129 |
- net.ParseIP(vtepStr), true); err != nil {
|
|
| 130 |
- logrus.Errorf("Peer delete failed in the driver: %v\n", err)
|
|
| 131 |
- } |
|
| 132 |
- } |
|
| 133 |
-} |
|
| 134 |
- |
|
| 135 |
-func (d *driver) startSerfLoop(eventCh chan serf.Event, notifyCh chan ovNotify, |
|
| 136 |
- exitCh chan chan struct{}) {
|
|
| 137 |
- |
|
| 138 |
- for {
|
|
| 139 |
- select {
|
|
| 140 |
- case notify, ok := <-notifyCh: |
|
| 141 |
- if !ok {
|
|
| 142 |
- break |
|
| 143 |
- } |
|
| 144 |
- |
|
| 145 |
- d.notifyEvent(notify) |
|
| 146 |
- case ch, ok := <-exitCh: |
|
| 147 |
- if !ok {
|
|
| 148 |
- break |
|
| 149 |
- } |
|
| 150 |
- |
|
| 151 |
- if err := d.serfInstance.Leave(); err != nil {
|
|
| 152 |
- logrus.Errorf("failed leaving the cluster: %v\n", err)
|
|
| 153 |
- } |
|
| 154 |
- |
|
| 155 |
- d.serfInstance.Shutdown() |
|
| 156 |
- close(ch) |
|
| 157 |
- return |
|
| 158 |
- case e, ok := <-eventCh: |
|
| 159 |
- if !ok {
|
|
| 160 |
- break |
|
| 161 |
- } |
|
| 162 |
- u, ok := e.(serf.UserEvent) |
|
| 163 |
- if !ok {
|
|
| 164 |
- break |
|
| 165 |
- } |
|
| 166 |
- d.processEvent(u) |
|
| 167 |
- } |
|
| 168 |
- } |
|
| 169 |
-} |
|
| 170 |
- |
|
| 171 |
-func (d *driver) isSerfAlive() bool {
|
|
| 172 |
- d.Lock() |
|
| 173 |
- serfInstance := d.serfInstance |
|
| 174 |
- d.Unlock() |
|
| 175 |
- if serfInstance == nil || serfInstance.State() != serf.SerfAlive {
|
|
| 176 |
- return false |
|
| 177 |
- } |
|
| 178 |
- return true |
|
| 179 |
-} |
| ... | ... |
@@ -3,7 +3,7 @@ package overlay |
| 3 | 3 |
//go:generate protoc -I.:../../Godeps/_workspace/src/github.com/gogo/protobuf --gogo_out=import_path=github.com/docker/libnetwork/drivers/overlay,Mgogoproto/gogo.proto=github.com/gogo/protobuf/gogoproto:. overlay.proto |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 |
- "fmt" |
|
| 6 |
+ "encoding/json" |
|
| 7 | 7 |
"net" |
| 8 | 8 |
"sync" |
| 9 | 9 |
|
| ... | ... |
@@ -12,40 +12,24 @@ import ( |
| 12 | 12 |
"github.com/docker/libnetwork/datastore" |
| 13 | 13 |
"github.com/docker/libnetwork/discoverapi" |
| 14 | 14 |
"github.com/docker/libnetwork/driverapi" |
| 15 |
- "github.com/docker/libnetwork/idm" |
|
| 16 | 15 |
"github.com/docker/libnetwork/netlabel" |
| 17 | 16 |
"github.com/docker/libnetwork/types" |
| 18 |
- "github.com/hashicorp/serf/serf" |
|
| 19 | 17 |
) |
| 20 | 18 |
|
| 21 | 19 |
const ( |
| 22 | 20 |
networkType = "overlay" |
| 23 | 21 |
vethPrefix = "veth" |
| 24 | 22 |
vethLen = 7 |
| 25 |
- vxlanIDStart = 4096 |
|
| 26 |
- vxlanIDEnd = (1 << 24) - 1 |
|
| 27 |
- vxlanPort = 4789 |
|
| 28 |
- vxlanEncap = 50 |
|
| 29 | 23 |
secureOption = "encrypted" |
| 30 | 24 |
) |
| 31 | 25 |
|
| 32 |
-var initVxlanIdm = make(chan (bool), 1) |
|
| 33 |
- |
|
| 34 | 26 |
type driver struct {
|
| 35 |
- eventCh chan serf.Event |
|
| 36 |
- notifyCh chan ovNotify |
|
| 37 |
- exitCh chan chan struct{}
|
|
| 38 |
- bindAddress string |
|
| 39 |
- advertiseAddress string |
|
| 40 |
- neighIP string |
|
| 41 |
- config map[string]interface{}
|
|
| 42 |
- serfInstance *serf.Serf |
|
| 43 |
- networks networkTable |
|
| 44 |
- store datastore.DataStore |
|
| 45 |
- localStore datastore.DataStore |
|
| 46 |
- vxlanIdm *idm.Idm |
|
| 47 |
- once sync.Once |
|
| 48 |
- joinOnce sync.Once |
|
| 27 |
+ config map[string]interface{}
|
|
| 28 |
+ networks networkTable |
|
| 29 |
+ store datastore.DataStore |
|
| 30 |
+ localStore datastore.DataStore |
|
| 31 |
+ once sync.Once |
|
| 32 |
+ joinOnce sync.Once |
|
| 49 | 33 |
sync.Mutex |
| 50 | 34 |
} |
| 51 | 35 |
|
| ... | ... |
@@ -84,92 +68,75 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
| 84 | 84 |
} |
| 85 | 85 |
} |
| 86 | 86 |
|
| 87 |
- d.restoreEndpoints() |
|
| 87 |
+ d.restoreHNSNetworks() |
|
| 88 | 88 |
|
| 89 | 89 |
return dc.RegisterDriver(networkType, d, c) |
| 90 | 90 |
} |
| 91 | 91 |
|
| 92 |
-// Endpoints are stored in the local store. Restore them and reconstruct the overlay sandbox |
|
| 93 |
-func (d *driver) restoreEndpoints() error {
|
|
| 94 |
- if d.localStore == nil {
|
|
| 95 |
- logrus.Warnf("Cannot restore overlay endpoints because local datastore is missing")
|
|
| 96 |
- return nil |
|
| 97 |
- } |
|
| 98 |
- kvol, err := d.localStore.List(datastore.Key(overlayEndpointPrefix), &endpoint{})
|
|
| 99 |
- if err != nil && err != datastore.ErrKeyNotFound {
|
|
| 100 |
- return fmt.Errorf("failed to read overlay endpoint from store: %v", err)
|
|
| 101 |
- } |
|
| 92 |
+func (d *driver) restoreHNSNetworks() error {
|
|
| 93 |
+ logrus.Infof("Restoring existing overlay networks from HNS into docker")
|
|
| 102 | 94 |
|
| 103 |
- if err == datastore.ErrKeyNotFound {
|
|
| 104 |
- return nil |
|
| 95 |
+ hnsresponse, err := hcsshim.HNSListNetworkRequest("GET", "", "")
|
|
| 96 |
+ if err != nil {
|
|
| 97 |
+ return err |
|
| 105 | 98 |
} |
| 106 | 99 |
|
| 107 |
- for _, kvo := range kvol {
|
|
| 108 |
- ep := kvo.(*endpoint) |
|
| 109 |
- |
|
| 110 |
- n := d.network(ep.nid) |
|
| 111 |
- if n == nil || ep.remote {
|
|
| 112 |
- if !ep.remote {
|
|
| 113 |
- logrus.Debugf("Network (%s) not found for restored endpoint (%s)", ep.nid[0:7], ep.id[0:7])
|
|
| 114 |
- logrus.Debugf("Deleting stale overlay endpoint (%s) from store", ep.id[0:7])
|
|
| 115 |
- } |
|
| 116 |
- |
|
| 117 |
- hcsshim.HNSEndpointRequest("DELETE", ep.profileId, "")
|
|
| 118 |
- |
|
| 119 |
- if err := d.deleteEndpointFromStore(ep); err != nil {
|
|
| 120 |
- logrus.Debugf("Failed to delete stale overlay endpoint (%s) from store", ep.id[0:7])
|
|
| 121 |
- } |
|
| 122 |
- |
|
| 100 |
+ for _, v := range hnsresponse {
|
|
| 101 |
+ if v.Type != networkType {
|
|
| 123 | 102 |
continue |
| 124 | 103 |
} |
| 125 | 104 |
|
| 126 |
- n.addEndpoint(ep) |
|
| 105 |
+ logrus.Infof("Restoring overlay network: %s", v.Name)
|
|
| 106 |
+ n := d.convertToOverlayNetwork(&v) |
|
| 107 |
+ d.addNetwork(n) |
|
| 108 |
+ |
|
| 109 |
+ // |
|
| 110 |
+ // We assume that any network will be recreated on daemon restart |
|
| 111 |
+ // and therefore don't restore hns endpoints for now |
|
| 112 |
+ // |
|
| 113 |
+ //n.restoreNetworkEndpoints() |
|
| 127 | 114 |
} |
| 128 | 115 |
|
| 129 | 116 |
return nil |
| 130 | 117 |
} |
| 131 | 118 |
|
| 132 |
-// Fini cleans up the driver resources |
|
| 133 |
-func Fini(drv driverapi.Driver) {
|
|
| 134 |
- d := drv.(*driver) |
|
| 135 |
- |
|
| 136 |
- if d.exitCh != nil {
|
|
| 137 |
- waitCh := make(chan struct{})
|
|
| 138 |
- |
|
| 139 |
- d.exitCh <- waitCh |
|
| 140 |
- |
|
| 141 |
- <-waitCh |
|
| 142 |
- } |
|
| 143 |
-} |
|
| 144 |
- |
|
| 145 |
-func (d *driver) configure() error {
|
|
| 146 |
- if d.store == nil {
|
|
| 147 |
- return nil |
|
| 148 |
- } |
|
| 149 |
- |
|
| 150 |
- if d.vxlanIdm == nil {
|
|
| 151 |
- return d.initializeVxlanIdm() |
|
| 152 |
- } |
|
| 119 |
+func (d *driver) convertToOverlayNetwork(v *hcsshim.HNSNetwork) *network {
|
|
| 120 |
+ n := &network{
|
|
| 121 |
+ id: v.Name, |
|
| 122 |
+ hnsId: v.Id, |
|
| 123 |
+ driver: d, |
|
| 124 |
+ endpoints: endpointTable{},
|
|
| 125 |
+ subnets: []*subnet{},
|
|
| 126 |
+ providerAddress: v.ManagementIP, |
|
| 127 |
+ } |
|
| 128 |
+ |
|
| 129 |
+ for _, hnsSubnet := range v.Subnets {
|
|
| 130 |
+ vsidPolicy := &hcsshim.VsidPolicy{}
|
|
| 131 |
+ for _, policy := range hnsSubnet.Policies {
|
|
| 132 |
+ if err := json.Unmarshal([]byte(policy), &vsidPolicy); err == nil && vsidPolicy.Type == "VSID" {
|
|
| 133 |
+ break |
|
| 134 |
+ } |
|
| 135 |
+ } |
|
| 153 | 136 |
|
| 154 |
- return nil |
|
| 155 |
-} |
|
| 137 |
+ gwIP := net.ParseIP(hnsSubnet.GatewayAddress) |
|
| 138 |
+ localsubnet := &subnet{
|
|
| 139 |
+ vni: uint32(vsidPolicy.VSID), |
|
| 140 |
+ gwIP: &gwIP, |
|
| 141 |
+ } |
|
| 156 | 142 |
|
| 157 |
-func (d *driver) initializeVxlanIdm() error {
|
|
| 158 |
- var err error |
|
| 143 |
+ _, subnetIP, err := net.ParseCIDR(hnsSubnet.AddressPrefix) |
|
| 159 | 144 |
|
| 160 |
- initVxlanIdm <- true |
|
| 161 |
- defer func() { <-initVxlanIdm }()
|
|
| 145 |
+ if err != nil {
|
|
| 146 |
+ logrus.Errorf("Error parsing subnet address %s ", hnsSubnet.AddressPrefix)
|
|
| 147 |
+ continue |
|
| 148 |
+ } |
|
| 162 | 149 |
|
| 163 |
- if d.vxlanIdm != nil {
|
|
| 164 |
- return nil |
|
| 165 |
- } |
|
| 150 |
+ localsubnet.subnetIP = subnetIP |
|
| 166 | 151 |
|
| 167 |
- d.vxlanIdm, err = idm.New(d.store, "vxlan-id", vxlanIDStart, vxlanIDEnd) |
|
| 168 |
- if err != nil {
|
|
| 169 |
- return fmt.Errorf("failed to initialize vxlan id manager: %v", err)
|
|
| 152 |
+ n.subnets = append(n.subnets, localsubnet) |
|
| 170 | 153 |
} |
| 171 | 154 |
|
| 172 |
- return nil |
|
| 155 |
+ return n |
|
| 173 | 156 |
} |
| 174 | 157 |
|
| 175 | 158 |
func (d *driver) Type() string {
|
| ... | ... |
@@ -180,122 +147,12 @@ func (d *driver) IsBuiltIn() bool {
|
| 180 | 180 |
return true |
| 181 | 181 |
} |
| 182 | 182 |
|
| 183 |
-func validateSelf(node string) error {
|
|
| 184 |
- advIP := net.ParseIP(node) |
|
| 185 |
- if advIP == nil {
|
|
| 186 |
- return fmt.Errorf("invalid self address (%s)", node)
|
|
| 187 |
- } |
|
| 188 |
- |
|
| 189 |
- addrs, err := net.InterfaceAddrs() |
|
| 190 |
- if err != nil {
|
|
| 191 |
- return fmt.Errorf("Unable to get interface addresses %v", err)
|
|
| 192 |
- } |
|
| 193 |
- for _, addr := range addrs {
|
|
| 194 |
- ip, _, err := net.ParseCIDR(addr.String()) |
|
| 195 |
- if err == nil && ip.Equal(advIP) {
|
|
| 196 |
- return nil |
|
| 197 |
- } |
|
| 198 |
- } |
|
| 199 |
- return fmt.Errorf("Multi-Host overlay networking requires cluster-advertise(%s) to be configured with a local ip-address that is reachable within the cluster", advIP.String())
|
|
| 200 |
-} |
|
| 201 |
- |
|
| 202 |
-func (d *driver) nodeJoin(advertiseAddress, bindAddress string, self bool) {
|
|
| 203 |
- if self && !d.isSerfAlive() {
|
|
| 204 |
- if err := validateSelf(advertiseAddress); err != nil {
|
|
| 205 |
- logrus.Errorf("%s", err.Error())
|
|
| 206 |
- } |
|
| 207 |
- |
|
| 208 |
- d.Lock() |
|
| 209 |
- d.advertiseAddress = advertiseAddress |
|
| 210 |
- d.bindAddress = bindAddress |
|
| 211 |
- d.Unlock() |
|
| 212 |
- |
|
| 213 |
- // If there is no cluster store there is no need to start serf. |
|
| 214 |
- if d.store != nil {
|
|
| 215 |
- err := d.serfInit() |
|
| 216 |
- if err != nil {
|
|
| 217 |
- logrus.Errorf("initializing serf instance failed: %v", err)
|
|
| 218 |
- return |
|
| 219 |
- } |
|
| 220 |
- } |
|
| 221 |
- } |
|
| 222 |
- |
|
| 223 |
- d.Lock() |
|
| 224 |
- if !self {
|
|
| 225 |
- d.neighIP = advertiseAddress |
|
| 226 |
- } |
|
| 227 |
- neighIP := d.neighIP |
|
| 228 |
- d.Unlock() |
|
| 229 |
- |
|
| 230 |
- if d.serfInstance != nil && neighIP != "" {
|
|
| 231 |
- var err error |
|
| 232 |
- d.joinOnce.Do(func() {
|
|
| 233 |
- err = d.serfJoin(neighIP) |
|
| 234 |
- if err == nil {
|
|
| 235 |
- d.pushLocalDb() |
|
| 236 |
- } |
|
| 237 |
- }) |
|
| 238 |
- if err != nil {
|
|
| 239 |
- logrus.Errorf("joining serf neighbor %s failed: %v", advertiseAddress, err)
|
|
| 240 |
- d.Lock() |
|
| 241 |
- d.joinOnce = sync.Once{}
|
|
| 242 |
- d.Unlock() |
|
| 243 |
- return |
|
| 244 |
- } |
|
| 245 |
- } |
|
| 246 |
-} |
|
| 247 |
- |
|
| 248 |
-func (d *driver) pushLocalEndpointEvent(action, nid, eid string) {
|
|
| 249 |
- n := d.network(nid) |
|
| 250 |
- if n == nil {
|
|
| 251 |
- logrus.Debugf("Error pushing local endpoint event for network %s", nid)
|
|
| 252 |
- return |
|
| 253 |
- } |
|
| 254 |
- ep := n.endpoint(eid) |
|
| 255 |
- if ep == nil {
|
|
| 256 |
- logrus.Debugf("Error pushing local endpoint event for ep %s / %s", nid, eid)
|
|
| 257 |
- return |
|
| 258 |
- } |
|
| 259 |
- |
|
| 260 |
- if !d.isSerfAlive() {
|
|
| 261 |
- return |
|
| 262 |
- } |
|
| 263 |
- d.notifyCh <- ovNotify{
|
|
| 264 |
- action: action, |
|
| 265 |
- nw: n, |
|
| 266 |
- ep: ep, |
|
| 267 |
- } |
|
| 268 |
-} |
|
| 269 |
- |
|
| 270 | 183 |
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster |
| 271 | 184 |
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
| 272 |
- |
|
| 273 |
- var err error |
|
| 274 |
- switch dType {
|
|
| 275 |
- case discoverapi.NodeDiscovery: |
|
| 276 |
- nodeData, ok := data.(discoverapi.NodeDiscoveryData) |
|
| 277 |
- if !ok || nodeData.Address == "" {
|
|
| 278 |
- return fmt.Errorf("invalid discovery data")
|
|
| 279 |
- } |
|
| 280 |
- d.nodeJoin(nodeData.Address, nodeData.BindAddress, nodeData.Self) |
|
| 281 |
- case discoverapi.DatastoreConfig: |
|
| 282 |
- if d.store != nil {
|
|
| 283 |
- return types.ForbiddenErrorf("cannot accept datastore configuration: Overlay driver has a datastore configured already")
|
|
| 284 |
- } |
|
| 285 |
- dsc, ok := data.(discoverapi.DatastoreConfigData) |
|
| 286 |
- if !ok {
|
|
| 287 |
- return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
|
| 288 |
- } |
|
| 289 |
- d.store, err = datastore.NewDataStoreFromConfig(dsc) |
|
| 290 |
- if err != nil {
|
|
| 291 |
- return types.InternalErrorf("failed to initialize data store: %v", err)
|
|
| 292 |
- } |
|
| 293 |
- default: |
|
| 294 |
- } |
|
| 295 |
- return nil |
|
| 185 |
+ return types.NotImplementedErrorf("not implemented")
|
|
| 296 | 186 |
} |
| 297 | 187 |
|
| 298 | 188 |
// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster |
| 299 | 189 |
func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
| 300 |
- return nil |
|
| 190 |
+ return types.NotImplementedErrorf("not implemented")
|
|
| 301 | 191 |
} |
| ... | ... |
@@ -7,40 +7,13 @@ import ( |
| 7 | 7 |
"encoding/json" |
| 8 | 8 |
|
| 9 | 9 |
"github.com/Sirupsen/logrus" |
| 10 |
+ "github.com/docker/libnetwork/types" |
|
| 10 | 11 |
|
| 11 | 12 |
"github.com/Microsoft/hcsshim" |
| 12 |
- "github.com/docker/libnetwork/types" |
|
| 13 | 13 |
) |
| 14 | 14 |
|
| 15 | 15 |
const ovPeerTable = "overlay_peer_table" |
| 16 | 16 |
|
| 17 |
-func (d *driver) pushLocalDb() {
|
|
| 18 |
- if !d.isSerfAlive() {
|
|
| 19 |
- return |
|
| 20 |
- } |
|
| 21 |
- |
|
| 22 |
- d.Lock() |
|
| 23 |
- networks := d.networks |
|
| 24 |
- d.Unlock() |
|
| 25 |
- |
|
| 26 |
- for _, n := range networks {
|
|
| 27 |
- n.Lock() |
|
| 28 |
- endpoints := n.endpoints |
|
| 29 |
- n.Unlock() |
|
| 30 |
- |
|
| 31 |
- for _, ep := range endpoints {
|
|
| 32 |
- if !ep.remote {
|
|
| 33 |
- d.notifyCh <- ovNotify{
|
|
| 34 |
- action: "join", |
|
| 35 |
- nw: n, |
|
| 36 |
- ep: ep, |
|
| 37 |
- } |
|
| 38 |
- |
|
| 39 |
- } |
|
| 40 |
- } |
|
| 41 |
- } |
|
| 42 |
-} |
|
| 43 |
- |
|
| 44 | 17 |
func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask, |
| 45 | 18 |
peerMac net.HardwareAddr, vtep net.IP, updateDb bool) error {
|
| 46 | 19 |
|
| ... | ... |
@@ -59,6 +32,7 @@ func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask, |
| 59 | 59 |
logrus.Info("WINOVERLAY: peerAdd: notifying HNS of the REMOTE endpoint")
|
| 60 | 60 |
|
| 61 | 61 |
hnsEndpoint := &hcsshim.HNSEndpoint{
|
| 62 |
+ Name: eid, |
|
| 62 | 63 |
VirtualNetwork: n.hnsId, |
| 63 | 64 |
MacAddress: peerMac.String(), |
| 64 | 65 |
IPAddress: peerIP, |
| ... | ... |
@@ -109,10 +83,6 @@ func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask, |
| 109 | 109 |
} |
| 110 | 110 |
|
| 111 | 111 |
n.addEndpoint(ep) |
| 112 |
- |
|
| 113 |
- if err := d.writeEndpointToStore(ep); err != nil {
|
|
| 114 |
- return fmt.Errorf("failed to update overlay endpoint %s to local store: %v", ep.id[0:7], err)
|
|
| 115 |
- } |
|
| 116 | 112 |
} |
| 117 | 113 |
|
| 118 | 114 |
return nil |
| ... | ... |
@@ -144,10 +114,6 @@ func (d *driver) peerDelete(nid, eid string, peerIP net.IP, peerIPMask net.IPMas |
| 144 | 144 |
} |
| 145 | 145 |
|
| 146 | 146 |
n.deleteEndpoint(eid) |
| 147 |
- |
|
| 148 |
- if err := d.deleteEndpointFromStore(ep); err != nil {
|
|
| 149 |
- logrus.Debugf("Failed to delete stale overlay endpoint (%s) from store", ep.id[0:7])
|
|
| 150 |
- } |
|
| 151 | 147 |
} |
| 152 | 148 |
|
| 153 | 149 |
return nil |
| ... | ... |
@@ -138,6 +138,7 @@ func getIPVSFamily() (int, error) {
|
| 138 | 138 |
if err != nil {
|
| 139 | 139 |
return 0, err |
| 140 | 140 |
} |
| 141 |
+ defer sock.Close() |
|
| 141 | 142 |
|
| 142 | 143 |
req := newGenlRequest(genlCtrlID, genlCtrlCmdGetFamily) |
| 143 | 144 |
req.AddData(nl.NewRtAttr(genlCtrlAttrFamilyName, nl.ZeroTerminated("IPVS")))
|
| ... | ... |
@@ -5,6 +5,7 @@ import ( |
| 5 | 5 |
"fmt" |
| 6 | 6 |
"net" |
| 7 | 7 |
|
| 8 |
+ "github.com/Sirupsen/logrus" |
|
| 8 | 9 |
"github.com/vishvananda/netlink" |
| 9 | 10 |
) |
| 10 | 11 |
|
| ... | ... |
@@ -96,6 +97,7 @@ func (n *networkNamespace) AddNeighbor(dstIP net.IP, dstMac net.HardwareAddr, op |
| 96 | 96 |
|
| 97 | 97 |
nh := n.findNeighbor(dstIP, dstMac) |
| 98 | 98 |
if nh != nil {
|
| 99 |
+ logrus.Debugf("Neighbor entry already present for IP %v, mac %v", dstIP, dstMac)
|
|
| 99 | 100 |
// If it exists silently return |
| 100 | 101 |
return nil |
| 101 | 102 |
} |