Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fetch container IPs directly from the namespace instead of calling 'weave ps' #3207

Merged
merged 6 commits into from
Jun 4, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
21 changes: 21 additions & 0 deletions probe/docker/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,15 @@ func isIPv4(addr string) bool {
return ip != nil && ip.To4() != nil
}

func contains(strs []string, str string) bool {
for _, s := range strs {
if s == str {
return true
}
}
return false
}

func (c *container) NetworkInfo(localAddrs []net.IP) report.Sets {
c.RLock()
defer c.RUnlock()
Expand All @@ -277,6 +286,18 @@ func (c *container) NetworkInfo(localAddrs []net.IP) report.Sets {
ips = append(ips, c.container.NetworkSettings.IPAddress)
}

// Fetch IP addresses from the container's namespace
cidrs, err := namespaceIPAddresses(c.container.State.Pid)
if err != nil {
log.Debugf("container %s: failed to get addresses: %s", c.container.ID, err)
}
for _, cidr := range cidrs {
ip := cidr.IP.String()
if !contains(ips, ip) {

This comment was marked as abuse.

ips = append(ips, ip)
}
}

// For now, for the proof-of-concept, we just add networks as a set of
// names. For the next iteration, we will probably want to create a new
// Network topology, populate the network nodes with all of the details
Expand Down
85 changes: 85 additions & 0 deletions probe/docker/network.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// withNetNS function requires a fix that first appeared in Go version 1.10
// +build go1.10

package docker

import (
"fmt"
"net"
"runtime"

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

// Code adapted from github.com/weaveworks/weave/net/netdev.go

// Return any non-local IP addresses for processID if in a non-root namespace
func namespaceIPAddresses(processID int) ([]*net.IPNet, error) {
// Ignore if this process is running in the root namespace
netnsRoot, err := netns.GetFromPid(1)
if err != nil {
return nil, fmt.Errorf("unable to open root namespace: %s", err)
}
defer netnsRoot.Close()
netnsContainer, err := netns.GetFromPid(processID)
if err != nil {
return nil, err
}
defer netnsContainer.Close()
if netnsRoot.Equal(netnsContainer) {
return nil, nil
}

var cidrs []*net.IPNet
err = withNetNS(netnsContainer, func() error {
cidrs, err = allNonLocalAddresses()
return err
})

return cidrs, err
}

// return all non-local IP addresses from the current namespace
func allNonLocalAddresses() ([]*net.IPNet, error) {
var cidrs []*net.IPNet
links, err := netlink.LinkList()
if err != nil {
return nil, err
}

for _, link := range links {
addrs, err := netlink.AddrList(link, netlink.FAMILY_ALL)
if err != nil {
return nil, err
}
for _, addr := range addrs {
// Exclude link-local ipv6 addresses, localhost, etc. Hope this is the correct test.
if addr.Scope == unix.RT_SCOPE_UNIVERSE {
cidrs = append(cidrs, addr.IPNet)
}
}
}
return cidrs, nil
}

// Run the 'work' function in a different network namespace
func withNetNS(ns netns.NsHandle, work func() error) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()

oldNs, err := netns.Get()
if err == nil {
defer oldNs.Close()

err = netns.Set(ns)
if err == nil {
defer netns.Set(oldNs)

err = work()
}
}

return err
}