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 }