github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/core/network/nic_test.go (about)

     1  // Copyright 2020 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package network_test
     5  
     6  import (
     7  	"strings"
     8  
     9  	"github.com/juju/errors"
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	"github.com/juju/juju/core/network"
    14  )
    15  
    16  type nicSuite struct {
    17  	info network.InterfaceInfos
    18  }
    19  
    20  var _ = gc.Suite(&nicSuite{})
    21  
    22  func (s *nicSuite) SetUpTest(_ *gc.C) {
    23  	s.info = network.InterfaceInfos{
    24  		{VLANTag: 1, DeviceIndex: 0, InterfaceName: "eth0", MACAddress: "00:16:3e:aa:bb:cc"},
    25  		{VLANTag: 0, DeviceIndex: 1, InterfaceName: "eth1"},
    26  		{VLANTag: 42, DeviceIndex: 2, InterfaceName: "br2"},
    27  		{ConfigType: network.ConfigDHCP, NoAutoStart: true},
    28  		{Addresses: network.ProviderAddresses{network.NewMachineAddress("0.1.2.3").AsProviderAddress()}},
    29  		{DNSServers: network.NewMachineAddresses([]string{"1.1.1.1", "2.2.2.2"}).AsProviderAddresses()},
    30  		{GatewayAddress: network.NewMachineAddress("4.3.2.1").AsProviderAddress()},
    31  		{AvailabilityZones: []string{"foo", "bar"}},
    32  		{Routes: []network.Route{{
    33  			DestinationCIDR: "0.1.2.3/24",
    34  			GatewayIP:       "0.1.2.1",
    35  			Metric:          0,
    36  		}}},
    37  		{DeviceIndex: 42, InterfaceName: "ovsbr0", VirtualPortType: network.OvsPort},
    38  	}
    39  }
    40  
    41  func (s *nicSuite) TestActualInterfaceName(c *gc.C) {
    42  	c.Check(s.info[0].ActualInterfaceName(), gc.Equals, "eth0.1")
    43  	c.Check(s.info[1].ActualInterfaceName(), gc.Equals, "eth1")
    44  	c.Check(s.info[2].ActualInterfaceName(), gc.Equals, "br2.42")
    45  }
    46  
    47  func (s *nicSuite) TestIsVirtual(c *gc.C) {
    48  	c.Check(s.info[0].IsVirtual(), jc.IsTrue)
    49  	c.Check(s.info[1].IsVirtual(), jc.IsFalse)
    50  	c.Check(s.info[2].IsVirtual(), jc.IsTrue)
    51  	c.Check(s.info[9].IsVirtual(), jc.IsTrue, gc.Commentf("expected NIC with OVS virtual port type to be treated as virtual"))
    52  }
    53  
    54  func (s *nicSuite) TestIsVLAN(c *gc.C) {
    55  	c.Check(s.info[0].IsVLAN(), jc.IsTrue)
    56  	c.Check(s.info[1].IsVLAN(), jc.IsFalse)
    57  	c.Check(s.info[2].IsVLAN(), jc.IsTrue)
    58  }
    59  
    60  func (s *nicSuite) TestAdditionalFields(c *gc.C) {
    61  	c.Check(s.info[3].ConfigType, gc.Equals, network.ConfigDHCP)
    62  	c.Check(s.info[3].NoAutoStart, jc.IsTrue)
    63  	c.Check(s.info[4].Addresses, jc.DeepEquals, network.ProviderAddresses{network.NewMachineAddress("0.1.2.3").AsProviderAddress()})
    64  	c.Check(s.info[5].DNSServers, jc.DeepEquals, network.NewMachineAddresses([]string{"1.1.1.1", "2.2.2.2"}).AsProviderAddresses())
    65  	c.Check(s.info[6].GatewayAddress, jc.DeepEquals, network.NewMachineAddress("4.3.2.1").AsProviderAddress())
    66  	c.Check(s.info[7].AvailabilityZones, jc.DeepEquals, []string{"foo", "bar"})
    67  	c.Check(s.info[8].Routes, jc.DeepEquals, []network.Route{{
    68  		DestinationCIDR: "0.1.2.3/24",
    69  		GatewayIP:       "0.1.2.1",
    70  		Metric:          0,
    71  	}})
    72  }
    73  
    74  func (*nicSuite) TestInterfaceInfoValidate(c *gc.C) {
    75  	dev := network.InterfaceInfo{InterfaceName: ""}
    76  	c.Check(dev.Validate(), jc.Satisfies, errors.IsNotValid)
    77  
    78  	dev = network.InterfaceInfo{MACAddress: "do you even MAC bro?"}
    79  	c.Check(dev.Validate(), jc.Satisfies, errors.IsNotValid)
    80  
    81  	dev = network.InterfaceInfo{
    82  		InterfaceName: "eth0",
    83  		MACAddress:    network.GenerateVirtualMACAddress(),
    84  		InterfaceType: "invalid",
    85  	}
    86  	c.Check(dev.Validate(), jc.Satisfies, errors.IsNotValid)
    87  
    88  	dev = network.InterfaceInfo{
    89  		InterfaceName: "not#valid",
    90  		InterfaceType: "bond",
    91  	}
    92  	c.Check(dev.Validate(), jc.ErrorIsNil)
    93  }
    94  
    95  func (*nicSuite) TestInterfaceInfosValidate(c *gc.C) {
    96  	c.Check(getInterFaceInfos().Validate(), jc.ErrorIsNil)
    97  }
    98  
    99  func (*nicSuite) TestInterfaceInfosFiltering(c *gc.C) {
   100  	filtered := getInterFaceInfos().Filter(func(iface network.InterfaceInfo) bool {
   101  		return strings.HasPrefix(iface.InterfaceName, "eth")
   102  	})
   103  
   104  	var devs []string
   105  	for _, iface := range filtered {
   106  		devs = append(devs, iface.ParentInterfaceName+":"+iface.InterfaceName)
   107  	}
   108  
   109  	c.Check(devs, gc.DeepEquals, []string{
   110  		":eth2",
   111  		"bond0:eth0",
   112  		"bond0:eth1",
   113  	})
   114  
   115  	// Filter again
   116  	filtered = filtered.Filter(func(iface network.InterfaceInfo) bool {
   117  		return iface.InterfaceName == "eth1"
   118  	})
   119  
   120  	devs = devs[0:0]
   121  	for _, iface := range filtered {
   122  		devs = append(devs, iface.ParentInterfaceName+":"+iface.InterfaceName)
   123  	}
   124  
   125  	c.Check(devs, gc.DeepEquals, []string{
   126  		"bond0:eth1",
   127  	})
   128  }
   129  
   130  func (s *nicSuite) TestInterfaceInfosGetByName(c *gc.C) {
   131  	devs := s.info.GetByName("wrong-name")
   132  	c.Assert(devs, gc.IsNil)
   133  
   134  	devs = s.info.GetByName("eth0")
   135  	c.Assert(devs, gc.HasLen, 1)
   136  }
   137  
   138  func (s *nicSuite) TestNormalizeMACAddress(c *gc.C) {
   139  	specs := []struct {
   140  		descr string
   141  		in    string
   142  		exp   string
   143  	}{
   144  		{
   145  			descr: "uppercased MAC",
   146  			in:    "AA:BB:CC:DD:EE:FF",
   147  			exp:   "aa:bb:cc:dd:ee:ff",
   148  		},
   149  		{
   150  			descr: "MAC with dashes instead of colons",
   151  			in:    "AA-BB-CC-DD-EE-FF",
   152  			exp:   "aa:bb:cc:dd:ee:ff",
   153  		},
   154  		{
   155  			descr: "already normalized MAC",
   156  			in:    "aa:bb:cc:dd:ee:ff",
   157  			exp:   "aa:bb:cc:dd:ee:ff",
   158  		},
   159  	}
   160  
   161  	for i, spec := range specs {
   162  		c.Logf("%d. %s", i, spec.descr)
   163  		got := network.NormalizeMACAddress(spec.in)
   164  		c.Assert(got, gc.Equals, spec.exp)
   165  	}
   166  }
   167  
   168  func getInterFaceInfos() network.InterfaceInfos {
   169  	return network.InterfaceInfos{
   170  		{
   171  			DeviceIndex:   0,
   172  			InterfaceName: "br-bond0",
   173  			InterfaceType: network.BondDevice,
   174  		},
   175  		{
   176  			DeviceIndex:   1,
   177  			InterfaceName: "eth2",
   178  			InterfaceType: network.EthernetDevice,
   179  		},
   180  		{
   181  			DeviceIndex:         2,
   182  			InterfaceName:       "bond0",
   183  			ParentInterfaceName: "br-bond0",
   184  			InterfaceType:       network.BondDevice,
   185  		},
   186  		{
   187  			DeviceIndex:         3,
   188  			InterfaceName:       "eth0",
   189  			ParentInterfaceName: "bond0",
   190  			InterfaceType:       network.BondDevice,
   191  		},
   192  		{
   193  			DeviceIndex:         4,
   194  			InterfaceName:       "eth1",
   195  			ParentInterfaceName: "bond0",
   196  			InterfaceType:       network.BondDevice,
   197  		},
   198  	}
   199  }