github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/core/network/discovery_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package network_test 5 6 import ( 7 "errors" 8 "net" 9 10 "github.com/juju/collections/set" 11 "github.com/juju/testing" 12 jc "github.com/juju/testing/checkers" 13 "go.uber.org/mock/gomock" 14 gc "gopkg.in/check.v1" 15 16 "github.com/juju/juju/core/network" 17 ) 18 19 type networkConfigSuite struct { 20 testing.IsolationSuite 21 22 source *MockConfigSource 23 24 ovsBridges set.Strings 25 defaultRouteGatewayIP net.IP 26 defaultRouteDevice string 27 bridgePorts map[string][]string 28 } 29 30 var _ = gc.Suite(&networkConfigSuite{}) 31 32 func (s *networkConfigSuite) SetUpTest(c *gc.C) { 33 s.IsolationSuite.SetUpTest(c) 34 35 s.ovsBridges = set.NewStrings() 36 s.defaultRouteGatewayIP = net.ParseIP("1.2.3.4") 37 s.defaultRouteDevice = "eth0" 38 s.bridgePorts = make(map[string][]string) 39 } 40 41 func (s *networkConfigSuite) TestGetObservedNetworkConfigInterfacesError(c *gc.C) { 42 defer s.setupMocks(c).Finish() 43 44 s.source.EXPECT().Interfaces().Return(nil, errors.New("boom")) 45 46 observedConfig, err := network.GetObservedNetworkConfig(s.source) 47 c.Check(err, gc.ErrorMatches, "detecting network interfaces: boom") 48 c.Check(observedConfig, gc.IsNil) 49 } 50 51 func (s *networkConfigSuite) TestGetObservedNetworkConfigInterfaceAddressesError(c *gc.C) { 52 ctrl := s.setupMocks(c) 53 defer ctrl.Finish() 54 55 nic := NewMockConfigSourceNIC(ctrl) 56 exp := nic.EXPECT() 57 exp.Name().Return("eth0").MinTimes(1) 58 exp.Type().Return(network.EthernetDevice).MinTimes(1) 59 exp.IsUp().Return(true) 60 exp.Index().Return(2) 61 exp.HardwareAddr().Return(net.HardwareAddr{}) 62 exp.MTU().Return(1500) 63 exp.Addresses().Return(nil, errors.New("bam")) 64 65 s.source.EXPECT().Interfaces().Return([]network.ConfigSourceNIC{nic}, nil) 66 67 observedConfig, err := network.GetObservedNetworkConfig(s.source) 68 c.Check(err, gc.ErrorMatches, `detecting addresses for "eth0": bam`) 69 c.Check(observedConfig, gc.IsNil) 70 } 71 72 func (s *networkConfigSuite) TestGetObservedNetworkConfigNilAddressError(c *gc.C) { 73 ctrl := s.setupMocks(c) 74 defer ctrl.Finish() 75 76 nic := NewMockConfigSourceNIC(ctrl) 77 exp := nic.EXPECT() 78 exp.Name().Return("eth1").MinTimes(1) 79 exp.Type().Return(network.EthernetDevice).MinTimes(1) 80 exp.IsUp().Return(true) 81 exp.Index().Return(2) 82 exp.HardwareAddr().Return(parseMAC(c, "aa:bb:cc:dd:ee:ff")) 83 exp.MTU().Return(1500) 84 exp.Addresses().Return([]network.ConfigSourceAddr{nil}, nil) 85 86 s.source.EXPECT().Interfaces().Return([]network.ConfigSourceNIC{nic}, nil) 87 88 observedConfig, err := network.GetObservedNetworkConfig(s.source) 89 c.Check(err, gc.ErrorMatches, `cannot parse nil address on interface "eth1"`) 90 c.Check(observedConfig, gc.IsNil) 91 } 92 93 func (s *networkConfigSuite) TestGetObservedNetworkConfigNoInterfaceAddresses(c *gc.C) { 94 ctrl := s.setupMocks(c) 95 defer ctrl.Finish() 96 97 nic := NewMockConfigSourceNIC(ctrl) 98 exp := nic.EXPECT() 99 100 // Note that eth1 is not the default gateway. 101 exp.Name().Return("eth1").MinTimes(1) 102 exp.Type().Return(network.EthernetDevice).MinTimes(1) 103 exp.IsUp().Return(true) 104 exp.Index().Return(2) 105 exp.HardwareAddr().Return(parseMAC(c, "aa:bb:cc:dd:ee:ff")) 106 exp.MTU().Return(1500) 107 exp.Addresses().Return(nil, nil) 108 109 s.source.EXPECT().Interfaces().Return([]network.ConfigSourceNIC{nic}, nil) 110 111 observedConfig, err := network.GetObservedNetworkConfig(s.source) 112 c.Assert(err, jc.ErrorIsNil) 113 114 c.Check(observedConfig, jc.DeepEquals, network.InterfaceInfos{{ 115 DeviceIndex: 2, 116 MACAddress: "aa:bb:cc:dd:ee:ff", 117 MTU: 1500, 118 InterfaceName: "eth1", 119 InterfaceType: "ethernet", 120 ConfigType: "manual", 121 Origin: network.OriginMachine, 122 }}) 123 } 124 125 func (s *networkConfigSuite) TestGetObservedNetworkConfigDefaultGatewayWithAddresses(c *gc.C) { 126 ctrl := s.setupMocks(c) 127 defer ctrl.Finish() 128 129 ip1, ipNet1, err := net.ParseCIDR("1.2.3.4/24") 130 c.Assert(err, jc.ErrorIsNil) 131 132 addr1 := NewMockConfigSourceAddr(ctrl) 133 addr1.EXPECT().IP().Return(ip1) 134 addr1.EXPECT().IPNet().Return(ipNet1) 135 addr1.EXPECT().IsSecondary().Return(false) 136 137 // Not the address not in CIDR form will result in config without a CIDR. 138 addr2 := NewMockConfigSourceAddr(ctrl) 139 addr2.EXPECT().IP().Return(net.ParseIP("559c:f8c5:812a:fa1f:21fe:5613:3f20:b081")) 140 addr2.EXPECT().IPNet().Return(nil) 141 addr2.EXPECT().IsSecondary().Return(true) 142 143 nic := NewMockConfigSourceNIC(ctrl) 144 exp := nic.EXPECT() 145 146 // eth0 matches the device returned as the default gateway. 147 exp.Name().Return("eth0").MinTimes(1) 148 exp.Type().Return(network.EthernetDevice).MinTimes(1) 149 exp.IsUp().Return(true) 150 exp.Index().Return(2) 151 exp.HardwareAddr().Return(parseMAC(c, "aa:bb:cc:dd:ee:ff")) 152 exp.MTU().Return(1500) 153 exp.Addresses().Return([]network.ConfigSourceAddr{addr1, addr2}, nil) 154 155 s.source.EXPECT().Interfaces().Return([]network.ConfigSourceNIC{nic}, nil) 156 157 observedConfig, err := network.GetObservedNetworkConfig(s.source) 158 c.Assert(err, jc.ErrorIsNil) 159 160 c.Check(observedConfig, jc.DeepEquals, network.InterfaceInfos{ 161 { 162 DeviceIndex: 2, 163 MACAddress: "aa:bb:cc:dd:ee:ff", 164 MTU: 1500, 165 InterfaceName: "eth0", 166 InterfaceType: "ethernet", 167 ConfigType: "static", 168 IsDefaultGateway: true, 169 GatewayAddress: network.NewMachineAddress("1.2.3.4").AsProviderAddress(), 170 Origin: network.OriginMachine, 171 Addresses: []network.ProviderAddress{ 172 network.NewMachineAddress( 173 "1.2.3.4", 174 network.WithCIDR("1.2.3.0/24"), 175 network.WithConfigType("static"), 176 network.WithScope("public"), 177 ).AsProviderAddress(), 178 network.NewMachineAddress( 179 "559c:f8c5:812a:fa1f:21fe:5613:3f20:b081", 180 network.WithConfigType("static"), 181 network.WithSecondary(true), 182 network.WithScope("public"), 183 ).AsProviderAddress(), 184 }, 185 }, 186 }) 187 } 188 189 func (s *networkConfigSuite) TestGetObservedNetworkConfigForOVSDevice(c *gc.C) { 190 s.ovsBridges.Add("ovsbr0") 191 192 ctrl := s.setupMocks(c) 193 defer ctrl.Finish() 194 195 nic := NewMockConfigSourceNIC(ctrl) 196 exp := nic.EXPECT() 197 198 exp.Name().Return("ovsbr0").MinTimes(1) 199 exp.Type().Return(network.BridgeDevice).MinTimes(1) 200 exp.IsUp().Return(true) 201 exp.Index().Return(2) 202 exp.HardwareAddr().Return(parseMAC(c, "aa:bb:cc:dd:ee:ff")) 203 exp.MTU().Return(1500) 204 exp.Addresses().Return(nil, nil) 205 206 s.source.EXPECT().Interfaces().Return([]network.ConfigSourceNIC{nic}, nil) 207 208 observedConfig, err := network.GetObservedNetworkConfig(s.source) 209 c.Assert(err, jc.ErrorIsNil) 210 211 c.Check(observedConfig, jc.DeepEquals, network.InterfaceInfos{{ 212 DeviceIndex: 2, 213 MACAddress: "aa:bb:cc:dd:ee:ff", 214 MTU: 1500, 215 InterfaceName: "ovsbr0", 216 InterfaceType: "bridge", 217 VirtualPortType: "openvswitch", 218 ConfigType: "manual", 219 Origin: network.OriginMachine, 220 }}) 221 } 222 223 func (s *networkConfigSuite) TestGetObservedNetworkConfigBridgePortsHaveParentSet(c *gc.C) { 224 s.bridgePorts["br-eth1"] = []string{"eth1"} 225 226 ctrl := s.setupMocks(c) 227 defer ctrl.Finish() 228 229 nic1 := NewMockConfigSourceNIC(ctrl) 230 exp1 := nic1.EXPECT() 231 232 exp1.Name().Return("eth1").MinTimes(1) 233 exp1.Type().Return(network.EthernetDevice).MinTimes(1) 234 exp1.IsUp().Return(true) 235 exp1.Index().Return(2) 236 exp1.HardwareAddr().Return(parseMAC(c, "aa:bb:cc:dd:ee:ff")) 237 exp1.MTU().Return(1500) 238 exp1.Addresses().Return(nil, nil) 239 240 nic2 := NewMockConfigSourceNIC(ctrl) 241 exp2 := nic2.EXPECT() 242 243 exp2.Name().Return("br-eth1").MinTimes(1) 244 exp2.Type().Return(network.BridgeDevice).MinTimes(1) 245 exp2.IsUp().Return(true) 246 exp2.Index().Return(3) 247 exp2.HardwareAddr().Return(parseMAC(c, "aa:bb:cc:dd:ee:ff")) 248 exp2.MTU().Return(1500) 249 exp2.Addresses().Return(nil, nil) 250 251 s.source.EXPECT().Interfaces().Return([]network.ConfigSourceNIC{nic1, nic2}, nil) 252 253 observedConfig, err := network.GetObservedNetworkConfig(s.source) 254 c.Assert(err, jc.ErrorIsNil) 255 256 c.Check(observedConfig, jc.DeepEquals, network.InterfaceInfos{ 257 { 258 DeviceIndex: 2, 259 MACAddress: "aa:bb:cc:dd:ee:ff", 260 MTU: 1500, 261 InterfaceName: "eth1", 262 InterfaceType: "ethernet", 263 ParentInterfaceName: "br-eth1", 264 ConfigType: "manual", 265 Origin: network.OriginMachine, 266 }, 267 { 268 DeviceIndex: 3, 269 MACAddress: "aa:bb:cc:dd:ee:ff", 270 MTU: 1500, 271 InterfaceName: "br-eth1", 272 InterfaceType: "bridge", 273 ConfigType: "manual", 274 Origin: network.OriginMachine, 275 }, 276 }) 277 } 278 279 func (s *networkConfigSuite) setupMocks(c *gc.C) *gomock.Controller { 280 ctrl := gomock.NewController(c) 281 282 s.source = NewMockConfigSource(ctrl) 283 exp := s.source.EXPECT() 284 exp.OvsManagedBridges().Return(s.ovsBridges, nil).MaxTimes(1) 285 exp.DefaultRoute().Return(s.defaultRouteGatewayIP, s.defaultRouteDevice, nil).MaxTimes(1) 286 287 if len(s.bridgePorts) == 0 { 288 exp.GetBridgePorts(gomock.Any()).Return(nil).AnyTimes() 289 } else { 290 for brName, ports := range s.bridgePorts { 291 exp.GetBridgePorts(brName).Return(ports) 292 } 293 } 294 295 return ctrl 296 } 297 298 func parseMAC(c *gc.C, val string) net.HardwareAddr { 299 mac, err := net.ParseMAC(val) 300 c.Assert(err, jc.ErrorIsNil) 301 return mac 302 }