Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions cmd/machine-config-daemon/node-ip.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package main

import (
"flag"
"fmt"
"net"

// Enable sha256 in container image references
_ "crypto/sha256"

"github.com/golang/glog"
"github.com/spf13/cobra"
"github.com/spf13/pflag"

"github.com/openshift/machine-config-operator/pkg/daemon/nodenet"
)

var nodeIPCmd = &cobra.Command{
Use: "node-ip",
DisableFlagsInUseLine: true,
Short: "Node IP tools",
Long: "Node IP has tools that aid in the configuration of nodes in platforms that use Virtual IPs",
}

var nodeIPShowCmd = &cobra.Command{
Use: "show",
DisableFlagsInUseLine: true,
Short: "Show a configured IP address that directly routes to the given Virtual IPs",
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
err := show(cmd, args)
if err != nil {
glog.Exitf("error in node-ip show: %v\n", err)
}
},
}

var nodeIPSetCmd = &cobra.Command{
Use: "set",
DisableFlagsInUseLine: true,
Short: "Sets container runtime services to bind to a configured IP address that directly routes to the given virtual IPs",
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
err := set(cmd, args)
if err != nil {
glog.Exitf("error in node-ip set: %v\n", err)
}
},
}

// init executes upon import
func init() {
rootCmd.AddCommand(nodeIPCmd)
nodeIPCmd.AddCommand(nodeIPShowCmd)
nodeIPCmd.AddCommand(nodeIPSetCmd)
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
flag.Set("logtostderr", "true")
flag.Parse()
}

func show(_ *cobra.Command, args []string) error {
vips := make([]net.IP, len(args))
for i, arg := range args {
vips[i] = net.ParseIP(arg)
if vips[i] == nil {
return fmt.Errorf("Failed to parse IP address %s", arg)
}
glog.V(3).Infof("Parsed Virtual IP %s", vips[i])
}

nodeAddrs, err := nodenet.AddressesRouting(vips, nodenet.NonDeprecatedAddress, nodenet.NonDefaultRoute)
if err != nil {
return err
}

if len(nodeAddrs) > 0 {
fmt.Println(nodeAddrs[0])
} else {
return fmt.Errorf("Failed to find node IP")
}

return nil
}

func set(_ *cobra.Command, args []string) error {
return nil
}
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,11 @@ require (
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.4.0
github.com/vincent-petithory/dataurl v0.0.0-20160330182126-9a301d65acbb
github.com/vishvananda/netlink v1.0.0
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3 // indirect
golang.org/x/net v0.0.0-20191109021931-daa7c04131f5 // indirect
golang.org/x/sys v0.0.0-20191002091554-b397fe3ad8ed // indirect
golang.org/x/sys v0.0.0-20191002091554-b397fe3ad8ed
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
golang.org/x/tools v0.0.0-20191002234911-9ade4c73f2af // indirect
gonum.org/v1/gonum v0.0.0-20190929233944-b20cf7805fc4 // indirect
Expand Down
141 changes: 141 additions & 0 deletions pkg/daemon/nodenet/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package nodenet

import (
"net"

"github.com/golang/glog"
"github.com/vishvananda/netlink"
"golang.org/x/sys/unix"
)

// AddressFilter is a function type to filter addresses
type AddressFilter func(netlink.Addr) bool

// RouteFilter is a function type to filter routes
type RouteFilter func(netlink.Route) bool

func getAddrs() (addrMap map[netlink.Link][]netlink.Addr, err error) {
nlHandle, err := netlink.NewHandle()
defer nlHandle.Delete()
if err != nil {
return nil, err
}

links, err := nlHandle.LinkList()
if err != nil {
return nil, err
}

addrMap = make(map[netlink.Link][]netlink.Addr)
for _, link := range links {
addresses, err := nlHandle.AddrList(link, netlink.FAMILY_ALL)
if err != nil {
return nil, err
}
for _, address := range addresses {
if _, ok := addrMap[link]; ok {
addrMap[link] = append(addrMap[link], address)
} else {
addrMap[link] = []netlink.Addr{address}
}
}
}
glog.V(2).Infof("retrieved Address map %+v", addrMap)
return addrMap, nil
}

func getRouteMap() (routeMap map[int][]netlink.Route, err error) {
nlHandle, err := netlink.NewHandle()
defer nlHandle.Delete()
if err != nil {
return nil, err
}

routes, err := nlHandle.RouteList(nil, netlink.FAMILY_V6)
if err != nil {
return nil, err
}

routeMap = make(map[int][]netlink.Route)
for _, route := range routes {
if route.Protocol != unix.RTPROT_RA {
glog.V(4).Infof("Ignoring route non Router advertisement route %+v", route)
continue
}
if _, ok := routeMap[route.LinkIndex]; ok {
routeMap[route.LinkIndex] = append(routeMap[route.LinkIndex], route)
} else {
routeMap[route.LinkIndex] = []netlink.Route{route}
}
}

glog.V(2).Infof("Retrieved IPv6 route map %+v", routeMap)

return routeMap, nil
}

// NonDeprecatedAddress returns true if the address is IPv6 and has a preferred lifetime of 0
func NonDeprecatedAddress(address netlink.Addr) bool {
return !(net.IPv6len == len(address.IP) && address.PreferedLft == 0)
}

// NonDefaultRoute returns whether the passed Route is the default
func NonDefaultRoute(route netlink.Route) bool {
return route.Dst != nil
}

// AddressesRouting takes a slice of Virtual IPs and returns a slice of configured addresses in the current network namespace that directly route to those vips. You can optionally pass an AddressFilter and/or RouteFilter to further filter down which addresses are considered
func AddressesRouting(vips []net.IP, af AddressFilter, rf RouteFilter) ([]net.IP, error) {
addrMap, err := getAddrs()
if err != nil {
return nil, err
}

var routeMap map[int][]netlink.Route
matches := make([]net.IP, 0)
for link, addresses := range addrMap {
for _, address := range addresses {
maskPrefix, maskBits := address.Mask.Size()
if !af(address) {
continue
}
if net.IPv6len == len(address.IP) && maskPrefix == maskBits {
if routeMap == nil {
routeMap, err = getRouteMap()
if err != nil {
panic(err)
}
}
if routes, ok := routeMap[link.Attrs().Index]; ok {
for _, route := range routes {
if !rf(route) {
continue
}
routePrefix, _ := route.Dst.Mask.Size()
glog.V(4).Infof("Checking route %+v (mask %s) for address %+v", route, route.Dst.Mask, address)
if routePrefix != 0 {
containmentNet := net.IPNet{IP: address.IP, Mask: route.Dst.Mask}
for _, vip := range vips {
glog.V(3).Infof("Checking whether address %s with route %s contains VIP %s", address, route, vip)
if containmentNet.Contains(vip) {
glog.V(2).Infof("Address %s with route %s contains VIP %s", address, route, vip)
matches = append(matches, address.IP)
}
}
}
}
}
} else {
for _, vip := range vips {
glog.V(3).Infof("Checking whether address %s contains VIP %s", address, vip)
if address.Contains(vip) {
glog.V(2).Infof("Address %s contains VIP %s", address, vip)
matches = append(matches, address.IP)
}
}
}
}

}
return matches, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ contents:
case "$STATUS" in
pre-up)
logger -s "NM non-virtual-ip-prepender triggered by pre-upping ${1}."
NON_VIRTUAL_IP=$(/usr/local/bin/non_virtual_ip \
NON_VIRTUAL_IP=$(/usr/local/bin/machine-config-daemon node-ip show \
"{{.Infra.Status.PlatformStatus.BareMetal.APIServerInternalIP}}" \
"{{.Infra.Status.PlatformStatus.BareMetal.NodeDNSIP}}" \
"{{.Infra.Status.PlatformStatus.BareMetal.IngressIP}}")
Expand Down Expand Up @@ -38,4 +38,4 @@ contents:
;;
*)
;;
esac
esac

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ contents:
case "$STATUS" in
pre-up)
logger -s "NM non-virtual-ip-prepender triggered by pre-upping ${1}."
NON_VIRTUAL_IP=$(/usr/local/bin/non_virtual_ip \
NON_VIRTUAL_IP=$(/usr/local/bin/machine-config-daemon node-ip show \
"{{.Infra.Status.PlatformStatus.OpenStack.APIServerInternalIP}}" \
"{{.Infra.Status.PlatformStatus.OpenStack.NodeDNSIP}}" \
"{{.Infra.Status.PlatformStatus.OpenStack.IngressIP}}")
Expand Down

This file was deleted.

12 changes: 0 additions & 12 deletions templates/worker/00-worker/ovirt/files/ovirt-non-virtual-ip.yaml

This file was deleted.