Skip to content

Commit 081564b

Browse files
author
Rajat Chopra
committed
One can now allocate hostsubnets for hosts that are not part of the cluster. This is useful when a host wants to be part of the SDN, but not part of the cluster (e.g. F5)
1 parent e8b8e2f commit 081564b

File tree

4 files changed

+55
-1
lines changed

4 files changed

+55
-1
lines changed

pkg/sdn/api/validation/validation.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
oapi "github.com/openshift/origin/pkg/api"
1010
sdnapi "github.com/openshift/origin/pkg/sdn/api"
11+
sdnplugin "github.com/openshift/origin/pkg/sdn/plugin"
1112
)
1213

1314
// ValidateClusterNetwork tests if required fields in the ClusterNetwork are set.
@@ -87,7 +88,10 @@ func ValidateHostSubnet(hs *sdnapi.HostSubnet) field.ErrorList {
8788

8889
_, _, err := net.ParseCIDR(hs.Subnet)
8990
if err != nil {
90-
allErrs = append(allErrs, field.Invalid(field.NewPath("subnet"), hs.Subnet, err.Error()))
91+
// check if annotation exists, then let the Subnet field be empty
92+
if _, ok := hs.Annotations[sdnplugin.AssignHostSubnetAnnotation]; !ok {
93+
allErrs = append(allErrs, field.Invalid(field.NewPath("subnet"), hs.Subnet, err.Error()))
94+
}
9195
}
9296
if net.ParseIP(hs.HostIP) == nil {
9397
allErrs = append(allErrs, field.Invalid(field.NewPath("hostIP"), hs.HostIP, "invalid IP address"))

pkg/sdn/plugin/plugin.go

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const (
2323
IngressBandwidthAnnotation string = "kubernetes.io/ingress-bandwidth"
2424
EgressBandwidthAnnotation string = "kubernetes.io/egress-bandwidth"
2525
AssignMacVlanAnnotation string = "pod.network.openshift.io/assign-macvlan"
26+
AssignHostSubnetAnnotation string = "pod.network.openshift.io/assign-subnet"
2627
)
2728

2829
func IsOpenShiftNetworkPlugin(pluginName string) bool {

pkg/sdn/plugin/subnets.go

+42
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ func (master *OsdnMaster) SubnetStartMaster(clusterNetwork *net.IPNet, hostSubne
4242
}
4343

4444
go utilwait.Forever(master.watchNodes, 0)
45+
go utilwait.Forever(master.watchSubnets, 0)
4546
return nil
4647
}
4748

@@ -240,6 +241,47 @@ func (node *OsdnNode) initSelfSubnet() error {
240241
return nil
241242
}
242243

244+
// Only run on the master
245+
// Watch for all hostsubnet events and if one is found with the right annotation, use the IPAM to dole a real subnet
246+
func (master *OsdnMaster) watchSubnets() {
247+
eventQueue := master.registry.RunEventQueue(HostSubnets)
248+
249+
for {
250+
eventType, obj, err := eventQueue.Pop()
251+
if err != nil {
252+
utilruntime.HandleError(fmt.Errorf("EventQueue failed for subnets: %v", err))
253+
return
254+
}
255+
hs := obj.(*osapi.HostSubnet)
256+
name := hs.ObjectMeta.Name
257+
hostIP := hs.HostIP
258+
259+
log.V(5).Infof("Watch %s event for HostSubnet %q", strings.Title(string(eventType)), name)
260+
switch eventType {
261+
case watch.Added, watch.Modified:
262+
if _, ok := hs.Annotations[AssignHostSubnetAnnotation]; ok {
263+
// Delete the annotated hostsubnet and create a new one with an assigned subnet
264+
// We do not update (instead of delete+create) because the watchSubnets on the nodes
265+
// will skip the event if it finds that the hostsubnet has the same host
266+
// And we cannot fix the watchSubnets code for node because it will break migration if
267+
// nodes are upgraded after the master
268+
err = master.registry.DeleteSubnet(name)
269+
if err != nil {
270+
log.Errorf("Error in deleting annotated subnet from master, name: %s, ip %s: %v", name, hostIP, err)
271+
continue
272+
}
273+
err = master.addNode(name, hostIP)
274+
if err != nil {
275+
log.Errorf("Error creating subnet for node %s, ip %s: %v", name, hostIP, err)
276+
continue
277+
}
278+
}
279+
case watch.Deleted:
280+
// ignore all deleted hostsubnets
281+
}
282+
}
283+
}
284+
243285
// Only run on the nodes
244286
func (node *OsdnNode) watchSubnets() {
245287
subnets := make(map[string]*osapi.HostSubnet)

pkg/util/netutils/subnet_allocator.go

+7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package netutils
33
import (
44
"fmt"
55
"net"
6+
"sync"
67
)
78

89
type SubnetAllocator struct {
@@ -14,6 +15,7 @@ type SubnetAllocator struct {
1415
rightMask uint32
1516
next uint32
1617
allocMap map[string]bool
18+
mutex sync.Mutex
1719
}
1820

1921
func NewSubnetAllocator(network string, hostBits uint32, inUse []string) (*SubnetAllocator, error) {
@@ -85,6 +87,9 @@ func (sna *SubnetAllocator) GetNetwork() (*net.IPNet, error) {
8587
numSubnets uint32
8688
numSubnetBits uint32
8789
)
90+
sna.mutex.Lock()
91+
defer sna.mutex.Unlock()
92+
8893
baseipu := IPToUint32(sna.network.IP)
8994
netMaskSize, _ := sna.network.Mask.Size()
9095
numSubnetBits = 32 - uint32(netMaskSize) - sna.hostBits
@@ -109,6 +114,8 @@ func (sna *SubnetAllocator) GetNetwork() (*net.IPNet, error) {
109114
}
110115

111116
func (sna *SubnetAllocator) ReleaseNetwork(ipnet *net.IPNet) error {
117+
sna.mutex.Lock()
118+
defer sna.mutex.Unlock()
112119
if !sna.network.Contains(ipnet.IP) {
113120
return fmt.Errorf("Provided subnet %v doesn't belong to the network %v.", ipnet, sna.network)
114121
}

0 commit comments

Comments
 (0)