Skip to content

Commit

Permalink
Merge pull request #17043 from pravisankar/validate-nodeip
Browse files Browse the repository at this point in the history
Automatic merge from submit-queue.

 Bug 1505266 - Validate node IP is local during sdn node initialization

Fix for https://bugzilla.redhat.com/show_bug.cgi?id=1505266
  • Loading branch information
openshift-merge-robot authored Oct 28, 2017
2 parents df394f2 + 75adfb4 commit f12efea
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 61 deletions.
33 changes: 33 additions & 0 deletions pkg/network/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import (
kapi "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/extensions"
kinternalinformers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"

"github.com/vishvananda/netlink"
)

func HostSubnetToString(subnet *networkapi.HostSubnet) string {
Expand Down Expand Up @@ -276,3 +278,34 @@ func RegisterSharedInformerEventHandlers(kubeInformers kinternalinformers.Shared
},
})
}

var (
ErrorNetworkInterfaceNotFound = fmt.Errorf("could not find network interface")
)

func GetLinkDetails(ip string) (netlink.Link, *net.IPNet, error) {
links, err := netlink.LinkList()
if err != nil {
return nil, nil, err
}

for _, link := range links {
addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
if err != nil {
glog.Warningf("Could not get addresses of interface %q: %v", link.Attrs().Name, err)
continue
}

for _, addr := range addrs {
if addr.IP.String() == ip {
_, ipNet, err := net.ParseCIDR(addr.IPNet.String())
if err != nil {
return nil, nil, fmt.Errorf("could not parse CIDR network from address %q: %v", ip, err)
}
return link, ipNet, nil
}
}
}

return nil, nil, ErrorNetworkInterfaceNotFound
}
45 changes: 10 additions & 35 deletions pkg/network/node/egressip.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,8 @@ type egressIPWatcher struct {
namespacesByVNID map[uint32]*namespaceEgress
namespacesByEgressIP map[string]*namespaceEgress

localEgressLink netlink.Link
localEgressNet *net.IPNet
localEgressIPMaskLen int
localEgressLink netlink.Link
localEgressNet *net.IPNet

testModeChan chan string
}
Expand All @@ -72,8 +71,10 @@ func newEgressIPWatcher(localIP string, oc *ovsController) *egressIPWatcher {
}

func (eip *egressIPWatcher) Start(networkClient networkclient.Interface, iptables *NodeIPTables) error {
if err := eip.findEgressLink(); err != nil {
return fmt.Errorf("could not find egress network interface: %v", err)
var err error
if eip.localEgressLink, eip.localEgressNet, err = common.GetLinkDetails(eip.localIP); err != nil {
// Not expected, should already be caught by node.New()
return err
}

eip.iptables = iptables
Expand All @@ -84,34 +85,6 @@ func (eip *egressIPWatcher) Start(networkClient networkclient.Interface, iptable
return nil
}

func (eip *egressIPWatcher) findEgressLink() error {
links, err := netlink.LinkList()
if err != nil {
return err
}
for _, link := range links {
addrs, err := netlink.AddrList(link, syscall.AF_INET)
if err != nil {
glog.Warningf("Could not get addresses of interface %q while trying to find egress interface: %v", link.Attrs().Name, err)
continue
}

for _, addr := range addrs {
if addr.IP.String() == eip.localIP {
_, eip.localEgressNet, err = net.ParseCIDR(addr.IPNet.String())
if err != nil {
return fmt.Errorf("could not parse CIDR network from address %q: %v", addr.IP.String(), err)
}
eip.localEgressLink = link
eip.localEgressIPMaskLen, _ = addr.Mask.Size()
return nil
}
}
}

return fmt.Errorf("could not find network interface with the address %q", eip.localIP)
}

func ipToHex(ip string) string {
bytes := net.ParseIP(ip)
if bytes == nil {
Expand Down Expand Up @@ -287,7 +260,8 @@ func (eip *egressIPWatcher) claimEgressIP(egressIP, egressHex string) error {
return nil
}

egressIPNet := fmt.Sprintf("%s/%d", egressIP, eip.localEgressIPMaskLen)
localEgressIPMaskLen, _ := eip.localEgressNet.Mask.Size()
egressIPNet := fmt.Sprintf("%s/%d", egressIP, localEgressIPMaskLen)
addr, err := netlink.ParseAddr(egressIPNet)
if err != nil {
return fmt.Errorf("could not parse egress IP %q: %v", egressIPNet, err)
Expand Down Expand Up @@ -321,7 +295,8 @@ func (eip *egressIPWatcher) releaseEgressIP(egressIP, egressHex string) error {
return nil
}

egressIPNet := fmt.Sprintf("%s/%d", egressIP, eip.localEgressIPMaskLen)
localEgressIPMaskLen, _ := eip.localEgressNet.Mask.Size()
egressIPNet := fmt.Sprintf("%s/%d", egressIP, localEgressIPMaskLen)
addr, err := netlink.ParseAddr(egressIPNet)
if err != nil {
return fmt.Errorf("could not parse egress IP %q: %v", egressIPNet, err)
Expand Down
70 changes: 44 additions & 26 deletions pkg/network/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,37 +143,18 @@ func New(c *OsdnNodeConfig) (network.NodeInterface, error) {
// Not an OpenShift plugin
return nil, nil
}
glog.Infof("Initializing SDN node of type %q with configured hostname %q (IP %q), iptables sync period %q", c.PluginName, c.Hostname, c.SelfIP, c.IPTablesSyncPeriod.String())

if useConnTrack && c.ProxyMode != componentconfig.ProxyModeIPTables {
return nil, fmt.Errorf("%q plugin is not compatible with proxy-mode %q", c.PluginName, c.ProxyMode)
}

// If our CNI config file exists, remove it so that kubelet doesn't think
// we're ready yet
os.Remove(filepath.Join(cniDirPath, openshiftCNIFile))

glog.Infof("Initializing SDN node of type %q with configured hostname %q (IP %q), iptables sync period %q", c.PluginName, c.Hostname, c.SelfIP, c.IPTablesSyncPeriod.String())
if c.Hostname == "" {
output, err := kexec.New().Command("uname", "-n").CombinedOutput()
if err != nil {
return nil, err
}
c.Hostname = strings.TrimSpace(string(output))
glog.Infof("Resolved hostname to %q", c.Hostname)
}
if c.SelfIP == "" {
var err error
c.SelfIP, err = netutils.GetNodeIP(c.Hostname)
if err != nil {
glog.V(5).Infof("Failed to determine node address from hostname %s; using default interface (%v)", c.Hostname, err)
var defaultIP net.IP
defaultIP, err = kubeutilnet.ChooseHostInterface()
if err != nil {
return nil, err
}
c.SelfIP = defaultIP.String()
glog.Infof("Resolved IP address to %q", c.SelfIP)
}
}

if useConnTrack && c.ProxyMode != componentconfig.ProxyModeIPTables {
return nil, fmt.Errorf("%q plugin is not compatible with proxy-mode %q", c.PluginName, c.ProxyMode)
if err := c.setNodeIP(); err != nil {
return nil, err
}

ovsif, err := ovs.New(kexec.New(), Br0, minOvsVersion)
Expand Down Expand Up @@ -215,6 +196,43 @@ func New(c *OsdnNodeConfig) (network.NodeInterface, error) {
return plugin, nil
}

// Set node IP if required
func (c *OsdnNodeConfig) setNodeIP() error {
if len(c.Hostname) == 0 {
output, err := kexec.New().Command("uname", "-n").CombinedOutput()
if err != nil {
return err
}
c.Hostname = strings.TrimSpace(string(output))
glog.Infof("Resolved hostname to %q", c.Hostname)
}

if len(c.SelfIP) == 0 {
var err error
c.SelfIP, err = netutils.GetNodeIP(c.Hostname)
if err != nil {
glog.V(5).Infof("Failed to determine node address from hostname %s; using default interface (%v)", c.Hostname, err)
var defaultIP net.IP
defaultIP, err = kubeutilnet.ChooseHostInterface()
if err != nil {
return err
}
c.SelfIP = defaultIP.String()
glog.Infof("Resolved IP address to %q", c.SelfIP)
}
}

if _, _, err := common.GetLinkDetails(c.SelfIP); err != nil {
if err == common.ErrorNetworkInterfaceNotFound {
return fmt.Errorf("node IP %q is not a local/private address (hostname %q)", c.SelfIP, c.Hostname)
} else {
return err
}
}

return nil
}

// Detect whether we are upgrading from a pre-CNI openshift and clean up
// interfaces and iptables rules that are no longer required
func (node *OsdnNode) dockerPreCNICleanup() error {
Expand Down

0 comments on commit f12efea

Please sign in to comment.