Skip to content

Commit

Permalink
f5 vxlan integration with sdn
Browse files Browse the repository at this point in the history
  • Loading branch information
Rajat Chopra authored and rajatchopra committed Oct 5, 2016
1 parent 3f47210 commit 3ad39a5
Show file tree
Hide file tree
Showing 17 changed files with 424 additions and 26 deletions.
6 changes: 6 additions & 0 deletions contrib/completions/bash/openshift
Original file line number Diff line number Diff line change
Expand Up @@ -19052,14 +19052,20 @@ _openshift_infra_f5-router()
local_nonpersistent_flags+=("--f5-https-vserver=")
flags+=("--f5-insecure")
local_nonpersistent_flags+=("--f5-insecure")
flags+=("--f5-internal-address=")
local_nonpersistent_flags+=("--f5-internal-address=")
flags+=("--f5-partition-path=")
local_nonpersistent_flags+=("--f5-partition-path=")
flags+=("--f5-password=")
local_nonpersistent_flags+=("--f5-password=")
flags+=("--f5-private-key=")
local_nonpersistent_flags+=("--f5-private-key=")
flags+=("--f5-setup-osdn-vxlan")
local_nonpersistent_flags+=("--f5-setup-osdn-vxlan")
flags+=("--f5-username=")
local_nonpersistent_flags+=("--f5-username=")
flags+=("--f5-vxlan-gateway-cidr=")
local_nonpersistent_flags+=("--f5-vxlan-gateway-cidr=")
flags+=("--fields=")
local_nonpersistent_flags+=("--fields=")
flags+=("--hostname-template=")
Expand Down
6 changes: 6 additions & 0 deletions contrib/completions/zsh/openshift
Original file line number Diff line number Diff line change
Expand Up @@ -19213,14 +19213,20 @@ _openshift_infra_f5-router()
local_nonpersistent_flags+=("--f5-https-vserver=")
flags+=("--f5-insecure")
local_nonpersistent_flags+=("--f5-insecure")
flags+=("--f5-internal-address=")
local_nonpersistent_flags+=("--f5-internal-address=")
flags+=("--f5-partition-path=")
local_nonpersistent_flags+=("--f5-partition-path=")
flags+=("--f5-password=")
local_nonpersistent_flags+=("--f5-password=")
flags+=("--f5-private-key=")
local_nonpersistent_flags+=("--f5-private-key=")
flags+=("--f5-setup-osdn-vxlan")
local_nonpersistent_flags+=("--f5-setup-osdn-vxlan")
flags+=("--f5-username=")
local_nonpersistent_flags+=("--f5-username=")
flags+=("--f5-vxlan-gateway-cidr=")
local_nonpersistent_flags+=("--f5-vxlan-gateway-cidr=")
flags+=("--fields=")
local_nonpersistent_flags+=("--fields=")
flags+=("--hostname-template=")
Expand Down
12 changes: 12 additions & 0 deletions docs/man/man1/openshift-infra-f5-router.1
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ that you must have a cluster\-wide administrative role to view all namespaces.
\fB\-\-f5\-insecure\fP=false
Skip strict certificate verification

.PP
\fB\-\-f5\-internal\-address\fP=""
The F5 BIG\-IP internal interface's IP address

.PP
\fB\-\-f5\-partition\-path\fP="/Common"
The F5 BIG\-IP partition path to use
Expand All @@ -86,10 +90,18 @@ that you must have a cluster\-wide administrative role to view all namespaces.
\fB\-\-f5\-private\-key\fP=""
The path to the F5 BIG\-IP SSH private key file

.PP
\fB\-\-f5\-setup\-osdn\-vxlan\fP=false
Flag to enable VxLAN setup for integration openshif\-sdn with the F5 BIG\-IP

.PP
\fB\-\-f5\-username\fP=""
The username for F5 BIG\-IP's management utility

.PP
\fB\-\-f5\-vxlan\-gateway\-cidr\fP=""
The F5 BIG\-IP gateway\-ip\-address/cidr\-mask for setting up the VxLAN

.PP
\fB\-\-fields\fP=""
A field selector to apply to routes to watch
Expand Down
41 changes: 33 additions & 8 deletions pkg/cmd/infra/router/f5.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,21 @@ type F5Router struct {
// normally used to create access control boundaries for users
// and applications.
PartitionPath string

// VxlanGateway is the ip address assigned to the local tunnel interface
// inside F5 box. This address is the one that the packets generated from F5
// will carry. The pods will return the packets to this address itself.
// It is important that the gateway be one of the ip addresses of the subnet
// that has been generated for F5.
VxlanGateway string

// InternalAddress is the ip address of the vtep interface used to connect to
// VxLAN overlay. It is the hostIP address listed in the subnet generated for F5
InternalAddress string

// SetupOSDNVxLAN is the boolean that conveys if F5 needs to setup a VxLAN
// to hook up with openshift-sdn
SetupOSDNVxLAN bool
}

// Bind binds F5Router arguments to flags
Expand All @@ -88,6 +103,9 @@ func (o *F5Router) Bind(flag *pflag.FlagSet) {
flag.StringVar(&o.PrivateKey, "f5-private-key", util.Env("ROUTER_EXTERNAL_HOST_PRIVKEY", ""), "The path to the F5 BIG-IP SSH private key file")
flag.BoolVar(&o.Insecure, "f5-insecure", util.Env("ROUTER_EXTERNAL_HOST_INSECURE", "") == "true", "Skip strict certificate verification")
flag.StringVar(&o.PartitionPath, "f5-partition-path", util.Env("ROUTER_EXTERNAL_HOST_PARTITION_PATH", f5plugin.F5DefaultPartitionPath), "The F5 BIG-IP partition path to use")
flag.StringVar(&o.InternalAddress, "f5-internal-address", util.Env("ROUTER_EXTERNAL_HOST_INTERNAL_ADDRESS", ""), "The F5 BIG-IP internal interface's IP address")
flag.StringVar(&o.VxlanGateway, "f5-vxlan-gateway-cidr", util.Env("ROUTER_EXTERNAL_HOST_VXLAN_GW_CIDR", ""), "The F5 BIG-IP gateway-ip-address/cidr-mask for setting up the VxLAN")
flag.BoolVar(&o.SetupOSDNVxLAN, "f5-setup-osdn-vxlan", false, "Flag to enable VxLAN setup for integration openshif-sdn with the F5 BIG-IP")
}

// Validate verifies the required F5 flags are present
Expand All @@ -108,6 +126,10 @@ func (o *F5Router) Validate() error {
return errors.New("F5 HTTP and HTTPS vservers cannot both be blank")
}

if o.SetupOSDNVxLAN && (len(o.VxlanGateway) == 0 || len(o.InternalAddress) == 0) {
return errors.New("For VxLAN setup, both internal-address and gateway-cidr must be specified")
}

return nil
}

Expand Down Expand Up @@ -157,14 +179,17 @@ func (o *F5RouterOptions) Validate() error {
// Run launches an F5 route sync process using the provided options. It never exits.
func (o *F5RouterOptions) Run() error {
cfg := f5plugin.F5PluginConfig{
Host: o.Host,
Username: o.Username,
Password: o.Password,
HttpVserver: o.HttpVserver,
HttpsVserver: o.HttpsVserver,
PrivateKey: o.PrivateKey,
Insecure: o.Insecure,
PartitionPath: o.PartitionPath,
Host: o.Host,
Username: o.Username,
Password: o.Password,
HttpVserver: o.HttpVserver,
HttpsVserver: o.HttpsVserver,
PrivateKey: o.PrivateKey,
Insecure: o.Insecure,
PartitionPath: o.PartitionPath,
InternalAddress: o.InternalAddress,
VxlanGateway: o.VxlanGateway,
SetupOSDNVxLAN: o.SetupOSDNVxLAN,
}
f5Plugin, err := f5plugin.NewF5Plugin(cfg)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions pkg/cmd/server/bootstrappolicy/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,7 @@ func GetBootstrapClusterRoles() []authorizationapi.ClusterRole {
Rules: []authorizationapi.PolicyRule{
authorizationapi.NewRule("list", "watch").Groups(kapiGroup).Resources("endpoints").RuleOrDie(),
authorizationapi.NewRule("list", "watch").Groups(kapiGroup).Resources("services").RuleOrDie(),
authorizationapi.NewRule("list", "watch").Groups(kapiGroup).Resources("nodes").RuleOrDie(),

authorizationapi.NewRule("list", "watch").Groups(routeGroup).Resources("routes").RuleOrDie(),
authorizationapi.NewRule("update").Groups(routeGroup).Resources("routes/status").RuleOrDie(),
Expand Down
29 changes: 28 additions & 1 deletion pkg/router/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,15 @@ type RouterController struct {

Plugin router.Plugin
NextRoute func() (watch.EventType, *routeapi.Route, error)
NextNode func() (watch.EventType, *kapi.Node, error)
NextEndpoints func() (watch.EventType, *kapi.Endpoints, error)

RoutesListConsumed func() bool
EndpointsListConsumed func() bool
NodesListConsumed func() bool
routesListConsumed bool
endpointsListConsumed bool
nodesListConsumed bool
filteredByNamespace bool

Namespaces NamespaceLister
Expand Down Expand Up @@ -78,6 +81,30 @@ func (c *RouterController) HandleNamespaces() {
glog.V(4).Infof("Unable to update list of namespaces")
}

// HandleNode handles a single Node event and synchronizes the router backend
func (c *RouterController) HandleNode() {
eventType, node, err := c.NextNode()
if err != nil {
utilruntime.HandleError(fmt.Errorf("unable to read nodes: %v", err))
return
}

c.lock.Lock()
defer c.lock.Unlock()

// Change the local sync state within the lock to ensure that all
// event handlers have the same view of sync state.
c.nodesListConsumed = c.NodesListConsumed()
c.updateLastSyncProcessed()

glog.V(4).Infof("Processing Node : %s", node.Name)
glog.V(4).Infof(" Event: %s", eventType)

if err := c.Plugin.HandleNode(eventType, node); err != nil {
utilruntime.HandleError(err)
}
}

// HandleRoute handles a single Route event and synchronizes the router backend.
func (c *RouterController) HandleRoute() {
eventType, route, err := c.NextRoute()
Expand Down Expand Up @@ -127,7 +154,7 @@ func (c *RouterController) HandleEndpoints() {
// updateLastSyncProcessed notifies the plugin if the most recent sync
// of router resources has been completed.
func (c *RouterController) updateLastSyncProcessed() {
lastSyncProcessed := c.endpointsListConsumed && c.routesListConsumed &&
lastSyncProcessed := c.endpointsListConsumed && c.routesListConsumed && c.nodesListConsumed &&
(c.Namespaces == nil || c.filteredByNamespace)
if err := c.Plugin.SetLastSyncProcessed(lastSyncProcessed); err != nil {
utilruntime.HandleError(err)
Expand Down
3 changes: 3 additions & 0 deletions pkg/router/controller/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ type fakeRouterPlugin struct {
func (p *fakeRouterPlugin) HandleRoute(t watch.EventType, route *routeapi.Route) error {
return nil
}
func (p *fakeRouterPlugin) HandleNode(t watch.EventType, node *kapi.Node) error {
return nil
}
func (p *fakeRouterPlugin) HandleEndpoints(watch.EventType, *kapi.Endpoints) error {
return nil
}
Expand Down
5 changes: 5 additions & 0 deletions pkg/router/controller/extended_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ func NewExtendedValidator(plugin router.Plugin, recorder RejectionRecorder) *Ext
}
}

// HandleNode processes watch events on the node resource
func (p *ExtendedValidator) HandleNode(eventType watch.EventType, node *kapi.Node) error {
return p.plugin.HandleNode(eventType, node)
}

// HandleEndpoints processes watch events on the Endpoints resource.
func (p *ExtendedValidator) HandleEndpoints(eventType watch.EventType, endpoints *kapi.Endpoints) error {
return p.plugin.HandleEndpoints(eventType, endpoints)
Expand Down
41 changes: 40 additions & 1 deletion pkg/router/controller/factory/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
type RouterControllerFactory struct {
KClient kclient.EndpointsNamespacer
OSClient osclient.RoutesNamespacer
NClient kclient.NodesInterface
Namespaces controller.NamespaceLister
ResyncInterval time.Duration
Namespace string
Expand All @@ -35,10 +36,11 @@ type RouterControllerFactory struct {
}

// NewDefaultRouterControllerFactory initializes a default router controller factory.
func NewDefaultRouterControllerFactory(oc osclient.RoutesNamespacer, kc kclient.EndpointsNamespacer) *RouterControllerFactory {
func NewDefaultRouterControllerFactory(oc osclient.RoutesNamespacer, kc kclient.Interface) *RouterControllerFactory {
return &RouterControllerFactory{
KClient: kc,
OSClient: oc,
NClient: kc,
ResyncInterval: 10 * time.Minute,

Namespace: kapi.NamespaceAll,
Expand All @@ -65,6 +67,13 @@ func (factory *RouterControllerFactory) Create(plugin router.Plugin) *controller
// we do not scope endpoints by labels or fields because the route labels != endpoints labels
}, &kapi.Endpoints{}, endpointsEventQueue, factory.ResyncInterval).Run()

nodeEventQueue := oscache.NewEventQueue(cache.MetaNamespaceKeyFunc)
cache.NewReflector(&nodeLW{
client: factory.NClient,
field: factory.Fields,
label: factory.Labels,
}, &kapi.Node{}, nodeEventQueue, factory.ResyncInterval).Run()

return &controller.RouterController{
Plugin: plugin,
NextEndpoints: func() (watch.EventType, *kapi.Endpoints, error) {
Expand All @@ -81,12 +90,22 @@ func (factory *RouterControllerFactory) Create(plugin router.Plugin) *controller
}
return eventType, obj.(*routeapi.Route), nil
},
NextNode: func() (watch.EventType, *kapi.Node, error) {
eventType, obj, err := nodeEventQueue.Pop()
if err != nil {
return watch.Error, nil, err
}
return eventType, obj.(*kapi.Node), nil
},
EndpointsListConsumed: func() bool {
return endpointsEventQueue.ListConsumed()
},
RoutesListConsumed: func() bool {
return routeEventQueue.ListConsumed()
},
NodesListConsumed: func() bool {
return nodeEventQueue.ListConsumed()
},
Namespaces: factory.Namespaces,
// check namespaces a bit more often than we resync events, so that we aren't always waiting
// the maximum interval for new items to come into the list
Expand Down Expand Up @@ -256,3 +275,23 @@ func (lw *endpointsLW) Watch(options kapi.ListOptions) (watch.Interface, error)
}
return lw.client.Endpoints(lw.namespace).Watch(opts)
}

// nodeLW is a list watcher for routes.
type nodeLW struct {
client kclient.NodesInterface
label labels.Selector
field fields.Selector
}

func (lw *nodeLW) List(options kapi.ListOptions) (runtime.Object, error) {
return lw.client.Nodes().List(options)
}

func (lw *nodeLW) Watch(options kapi.ListOptions) (watch.Interface, error) {
opts := kapi.ListOptions{
LabelSelector: lw.label,
FieldSelector: lw.field,
ResourceVersion: options.ResourceVersion,
}
return lw.client.Nodes().Watch(opts)
}
4 changes: 4 additions & 0 deletions pkg/router/controller/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,10 @@ func (a *StatusAdmitter) HandleRoute(eventType watch.EventType, route *routeapi.
return a.plugin.HandleRoute(eventType, route)
}

func (a *StatusAdmitter) HandleNode(eventType watch.EventType, node *kapi.Node) error {
return a.plugin.HandleNode(eventType, node)
}

func (a *StatusAdmitter) HandleEndpoints(eventType watch.EventType, route *kapi.Endpoints) error {
return a.plugin.HandleEndpoints(eventType, route)
}
Expand Down
5 changes: 5 additions & 0 deletions pkg/router/controller/unique_host.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ func (p *UniqueHost) HandleEndpoints(eventType watch.EventType, endpoints *kapi.
return p.plugin.HandleEndpoints(eventType, endpoints)
}

// HandleNode processes watch events on the Node resource and calls the router
func (p *UniqueHost) HandleNode(eventType watch.EventType, node *kapi.Node) error {
return p.plugin.HandleNode(eventType, node)
}

// HandleRoute processes watch events on the Route resource.
// TODO: this function can probably be collapsed with the router itself, as a function that
// determines which component needs to be recalculated (which template) and then does so
Expand Down
Loading

0 comments on commit 3ad39a5

Please sign in to comment.