func (rb *HostgwBackend) handleSubnetEvents(batch subnet.EventBatch) { for _, evt := range batch { switch evt.Type { case subnet.SubnetAdded: log.Infof("Subnet added: %v via %v", evt.Lease.Network, evt.Lease.Attrs.PublicIP) if evt.Lease.Attrs.BackendType != "host-gw" { log.Warningf("Ignoring non-host-gw subnet: type=%v", evt.Lease.Attrs.BackendType) continue } route := netlink.Route{ Dst: evt.Lease.Network.ToIPNet(), Gw: evt.Lease.Attrs.PublicIP.ToIP(), LinkIndex: rb.extIface.Index, } if err := netlink.RouteAdd(&route); err != nil { log.Errorf("Error adding route to %v via %v: %v", evt.Lease.Network, evt.Lease.Attrs.PublicIP, err) continue } case subnet.SubnetRemoved: log.Info("Subnet removed: ", evt.Lease.Network) if evt.Lease.Attrs.BackendType != "host-gw" { log.Warningf("Ignoring non-host-gw subnet: type=%v", evt.Lease.Attrs.BackendType) continue } route := netlink.Route{ Dst: evt.Lease.Network.ToIPNet(), Gw: evt.Lease.Attrs.PublicIP.ToIP(), LinkIndex: rb.extIface.Index, } if err := netlink.RouteDel(&route); err != nil { log.Errorf("Error deleting route to %v: %v", evt.Lease.Network, err) continue } default: log.Error("Internal error: unknown event type: ", int(evt.Type)) } } }
func (sm *SubnetManager) tryAcquireLease(extIP ip.IP4, attrs *LeaseAttrs) (ip.IP4Net, error) { sm.mtx.Lock() defer sm.mtx.Unlock() var err error sm.leases, err = sm.getLeases() if err != nil { return ip.IP4Net{}, err } attrBytes, err := json.Marshal(attrs) if err != nil { log.Errorf("marshal failed: %#v, %v", attrs, err) return ip.IP4Net{}, err } // try to reuse a subnet if there's one that matches our IP if l := findLeaseByIP(sm.leases, extIP); l != nil { resp, err := sm.registry.UpdateSubnet(l.Network.StringSep(".", "-"), string(attrBytes), subnetTTL) if err != nil { return ip.IP4Net{}, err } sm.myLease.Network = l.Network sm.myLease.Attrs = *attrs sm.leaseExp = *resp.Expiration return l.Network, nil } // no existing match, grab a new one sn, err := sm.allocateSubnet() if err != nil { return ip.IP4Net{}, err } resp, err := sm.registry.CreateSubnet(sn.StringSep(".", "-"), string(attrBytes), subnetTTL) switch { case err == nil: sm.myLease.Network = sn sm.myLease.Attrs = *attrs sm.leaseExp = *resp.Expiration return sn, nil case err == ErrSubnetExists: // if subnet already exists, try again. return ip.IP4Net{}, nil default: return ip.IP4Net{}, err } }
func (sm *SubnetManager) WatchLeases(receiver chan EventBatch, cancel chan bool) { // "catch up" by replaying all the leases we discovered during // AcquireLease var batch EventBatch sm.mtx.RLock() for _, l := range sm.leases { if !sm.myLease.Network.Equal(l.Network) { batch = append(batch, Event{SubnetAdded, l}) } } sm.mtx.RUnlock() if len(batch) > 0 { receiver <- batch } for { resp, err := sm.registry.WatchSubnets(sm.lastIndex+1, cancel) // WatchSubnets exited by cancel chan being signaled if err == nil && resp == nil { return } var batch *EventBatch if err == nil { batch, err = sm.parseSubnetWatchResponse(resp) } else { batch, err = sm.parseSubnetWatchError(err) } if err != nil { log.Errorf("%v", err) time.Sleep(time.Second) continue } if batch != nil { receiver <- *batch } } }
func (sm *SubnetManager) applySubnetChange(action string, ipn ip.IP4Net, data []byte) (Event, error) { sm.mtx.Lock() defer sm.mtx.Unlock() switch action { case "delete", "expire": for i, l := range sm.leases { if l.Network.Equal(ipn) { deleteLease(sm.leases, i) return Event{SubnetRemoved, l}, nil } } log.Errorf("Removed subnet (%s) was not found", ipn) return Event{ SubnetRemoved, SubnetLease{ipn, LeaseAttrs{}}, }, nil default: var attrs LeaseAttrs err := json.Unmarshal(data, &attrs) if err != nil { return Event{}, err } for i, l := range sm.leases { if l.Network.Equal(ipn) { sm.leases[i] = SubnetLease{ipn, attrs} return Event{SubnetAdded, sm.leases[i]}, nil } } sm.leases = append(sm.leases, SubnetLease{ipn, attrs}) return Event{SubnetAdded, sm.leases[len(sm.leases)-1]}, nil } }