diff --git a/client/fingerprint/network_test.go b/client/fingerprint/network_test.go index f99c91830..650488bb1 100644 --- a/client/fingerprint/network_test.go +++ b/client/fingerprint/network_test.go @@ -17,30 +17,32 @@ var ( HardwareAddr: []byte{23, 43, 54, 54}, Flags: net.FlagUp | net.FlagLoopback, } + + eth0 = net.Interface{ + Index: 3, + MTU: 1500, + Name: "eth0", + HardwareAddr: []byte{23, 44, 54, 67}, + Flags: net.FlagUp | net.FlagMulticast | net.FlagBroadcast, + } + + eth1 = net.Interface{ + Index: 4, + MTU: 1500, + Name: "eth1", + HardwareAddr: []byte{23, 44, 54, 69}, + Flags: net.FlagMulticast | net.FlagBroadcast, + } + + eth2 = net.Interface{ + Index: 4, + MTU: 1500, + Name: "eth2", + HardwareAddr: []byte{23, 44, 54, 70}, + Flags: net.FlagUp | net.FlagBroadcast | net.FlagMulticast, + } ) -type LoAddrV4 struct { -} - -func (l LoAddrV4) Network() string { - return "ip+net" -} - -func (l LoAddrV4) String() string { - return "127.0.0.1/8" -} - -type LoAddrV6 struct { -} - -func (l LoAddrV6) Network() string { - return "ip+net" -} - -func (l LoAddrV6) String() string { - return "::1/128" -} - // A fake network detector which returns no devices type NetworkIntefaceDetectorNoDevices struct { } @@ -79,6 +81,59 @@ func (n *NetworkInterfaceDetectorOnlyLo) Addrs(intf *net.Interface) ([]net.Addr, _, ipnet2, _ := net.ParseCIDR("2001:DB8::/48") return []net.Addr{ipnet1, ipnet2}, nil } + + return nil, fmt.Errorf("Can't find addresses for device: %v", intf.Name) +} + +// A fake network detector which simulates the presence of multiple interfaces +type NetworkInterfaceDetectorMultipleInterfaces struct { +} + +func (n *NetworkInterfaceDetectorMultipleInterfaces) Interfaces() ([]net.Interface, error) { + return []net.Interface{lo, eth0, eth1, eth2}, nil +} + +func (n *NetworkInterfaceDetectorMultipleInterfaces) InterfaceByName(name string) (*net.Interface, error) { + var intf *net.Interface + switch name { + case "lo": + intf = &lo + case "eth0": + intf = ð0 + case "eth1": + intf = ð1 + case "eth2": + intf = ð2 + } + if intf != nil { + return intf, nil + } + + return nil, fmt.Errorf("No device with name %v found", name) +} + +func (n *NetworkInterfaceDetectorMultipleInterfaces) Addrs(intf *net.Interface) ([]net.Addr, error) { + if intf.Name == "lo" { + _, ipnet1, _ := net.ParseCIDR("127.0.0.1/8") + _, ipnet2, _ := net.ParseCIDR("2001:DB8::/48") + return []net.Addr{ipnet1, ipnet2}, nil + } + + if intf.Name == "eth0" { + _, ipnet1, _ := net.ParseCIDR("100.64.0.11/10") + _, ipnet2, _ := net.ParseCIDR("2005:DB6::/48") + return []net.Addr{ipnet1, ipnet2}, nil + } + + if intf.Name == "eth1" { + _, ipnet1, _ := net.ParseCIDR("100.64.0.10/10") + _, ipnet2, _ := net.ParseCIDR("2003:DB8::/48") + return []net.Addr{ipnet1, ipnet2}, nil + } + + if intf.Name == "eth2" { + return []net.Addr{}, nil + } return nil, fmt.Errorf("Can't find addresses for device: %v", intf.Name) } @@ -201,3 +256,46 @@ func TestNetworkFingerPrint_default_device(t *testing.T) { t.Fatal("Expected Network Resource to have a non-zero bandwith") } } + +func TestNetworkFingerPrint_excludelo_down_interfaces(t *testing.T) { + f := &NetworkFingerprint{logger: testLogger(), interfaceDetector: &NetworkInterfaceDetectorMultipleInterfaces{}} + node := &structs.Node{ + Attributes: make(map[string]string), + } + cfg := &config.Config{NetworkSpeed: 100} + + ok, err := f.Fingerprint(cfg, node) + if err != nil { + t.Fatalf("err: %v", err) + } + if !ok { + t.Fatalf("should apply") + } + + assertNodeAttributeContains(t, node, "network.ip-address") + + ip := node.Attributes["network.ip-address"] + match := net.ParseIP(ip) + if match == nil { + t.Fatalf("Bad IP match: %s", ip) + } + + if node.Resources == nil || len(node.Resources.Networks) == 0 { + t.Fatal("Expected to find Network Resources") + } + + // Test at least the first Network Resource + net := node.Resources.Networks[0] + if net.IP == "" { + t.Fatal("Expected Network Resource to have an IP") + } + if net.CIDR == "" { + t.Fatal("Expected Network Resource to have a CIDR") + } + if net.Device != "eth0" { + t.Fatal("Expected Network Resource to be eth0. Actual: ", net.Device) + } + if net.MBits == 0 { + t.Fatal("Expected Network Resource to have a non-zero bandwith") + } +} diff --git a/client/fingerprint/network_unix.go b/client/fingerprint/network_unix.go index 1f82d52fd..0e47787ca 100644 --- a/client/fingerprint/network_unix.go +++ b/client/fingerprint/network_unix.go @@ -209,7 +209,7 @@ func (f *NetworkFingerprint) deviceHasIpAddress(intf *net.Interface) bool { } func (n *NetworkFingerprint) isDeviceLoopBackOrPointToPoint(intf *net.Interface) bool { - return intf.Flags&(net.FlagLoopback|net.FlagPointToPoint) == 0 + return intf.Flags&(net.FlagLoopback|net.FlagPointToPoint) != 0 } // Returns the interface with the name passed by user @@ -217,7 +217,7 @@ func (n *NetworkFingerprint) isDeviceLoopBackOrPointToPoint(intf *net.Interface) // and finds one which is routable and marked as UP // It excludes PPP and lo devices unless they are specifically asked func (f *NetworkFingerprint) findInterface(deviceName string) (*net.Interface, error) { - var interfaces []*net.Interface + var interfaces []net.Interface var err error if deviceName != "" { @@ -232,12 +232,12 @@ func (f *NetworkFingerprint) findInterface(deviceName string) (*net.Interface, e for _, intf := range intfs { if f.isDeviceEnabled(&intf) && !f.isDeviceLoopBackOrPointToPoint(&intf) && f.deviceHasIpAddress(&intf) { - interfaces = append(interfaces, &intf) + interfaces = append(interfaces, intf) } } if len(interfaces) == 0 { return nil, errors.New("No network interfaces were detected") } - return interfaces[0], nil + return &interfaces[0], nil }