github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/state/ipaddresses_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package state_test 5 6 import ( 7 "fmt" 8 "sort" 9 10 "github.com/juju/collections/set" 11 "github.com/juju/errors" 12 jc "github.com/juju/testing/checkers" 13 gc "gopkg.in/check.v1" 14 15 "github.com/juju/juju/core/network" 16 "github.com/juju/juju/state" 17 ) 18 19 // ipAddressesStateSuite contains white-box tests for IP addresses of link-layer 20 // devices, which include access to mongo. 21 type ipAddressesStateSuite struct { 22 ConnSuite 23 24 machine *state.Machine 25 26 otherState *state.State 27 otherStateMachine *state.Machine 28 } 29 30 var _ = gc.Suite(&ipAddressesStateSuite{}) 31 32 type AddressSorter []*state.Address 33 34 func (a AddressSorter) Len() int { return len(a) } 35 func (a AddressSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 36 func (a AddressSorter) Less(i, j int) bool { return a[i].DocID() < a[j].DocID() } 37 38 var _ sort.Interface = (AddressSorter)(nil) 39 40 func (s *ipAddressesStateSuite) SetUpTest(c *gc.C) { 41 s.ConnSuite.SetUpTest(c) 42 43 var err error 44 s.machine, err = s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 45 c.Assert(err, jc.ErrorIsNil) 46 47 s.otherState = s.NewStateForModelNamed(c, "other-model") 48 s.otherStateMachine, err = s.otherState.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 49 c.Assert(err, jc.ErrorIsNil) 50 51 // Add the few subnets used by the tests into both models. 52 subnetInfos := []network.SubnetInfo{{ 53 CIDR: "0.1.2.0/24", 54 }, { 55 CIDR: "fc00::/64", 56 }, { 57 CIDR: "10.20.0.0/16", 58 }, { 59 CIDR: "30.30.30.0/24", 60 }, { 61 CIDR: "252.80.0.0/12", 62 FanInfo: &network.FanCIDRs{ 63 FanLocalUnderlay: "30.30.30.0/24", 64 FanOverlay: "252.0.0.0/8", 65 }, 66 }} 67 for _, info := range subnetInfos { 68 _, err = s.State.AddSubnet(info) 69 c.Check(err, jc.ErrorIsNil) 70 _, err = s.otherState.AddSubnet(info) 71 c.Check(err, jc.ErrorIsNil) 72 } 73 } 74 75 func (s *ipAddressesStateSuite) TestMachineMethodReturnsMachine(c *gc.C) { 76 _, addresses := s.addNamedDeviceWithAddresses(c, "eth0", "0.1.2.3/24") 77 78 result, err := addresses[0].Machine() 79 c.Assert(err, jc.ErrorIsNil) 80 c.Assert(result, jc.DeepEquals, s.machine) 81 } 82 83 func (s *ipAddressesStateSuite) addNamedDeviceWithAddresses( 84 c *gc.C, name string, addresses ...string, 85 ) (*state.LinkLayerDevice, []*state.Address) { 86 device := s.addNamedDevice(c, name) 87 88 addressesArgs := make([]state.LinkLayerDeviceAddress, len(addresses)) 89 for i, address := range addresses { 90 addressesArgs[i] = state.LinkLayerDeviceAddress{ 91 DeviceName: name, 92 ConfigMethod: network.ConfigStatic, 93 CIDRAddress: address, 94 } 95 } 96 err := s.machine.SetDevicesAddresses(addressesArgs...) 97 c.Assert(err, jc.ErrorIsNil) 98 deviceAddresses, err := device.Addresses() 99 c.Assert(err, jc.ErrorIsNil) 100 c.Assert(deviceAddresses, gc.HasLen, len(addresses)) 101 return device, deviceAddresses 102 } 103 104 func (s *ipAddressesStateSuite) addNamedDevice(c *gc.C, name string) *state.LinkLayerDevice { 105 return s.addNamedDeviceForMachine(c, name, s.machine) 106 } 107 108 func (s *ipAddressesStateSuite) addNamedDeviceForMachine( 109 c *gc.C, name string, machine *state.Machine, 110 ) *state.LinkLayerDevice { 111 deviceArgs := state.LinkLayerDeviceArgs{ 112 Name: name, 113 Type: network.EthernetDevice, 114 } 115 err := machine.SetLinkLayerDevices(deviceArgs) 116 c.Assert(err, jc.ErrorIsNil) 117 device, err := machine.LinkLayerDevice(name) 118 c.Assert(err, jc.ErrorIsNil) 119 return device 120 } 121 122 func (s *ipAddressesStateSuite) TestMachineMethodReturnsNotFoundErrorWhenMissing(c *gc.C) { 123 _, addresses := s.addNamedDeviceWithAddresses(c, "eth0", "0.1.2.3/24") 124 s.ensureMachineDeadAndRemove(c, s.machine) 125 126 result, err := addresses[0].Machine() 127 c.Assert(err, gc.ErrorMatches, "machine 0 not found") 128 c.Assert(err, jc.Satisfies, errors.IsNotFound) 129 c.Assert(result, gc.IsNil) 130 } 131 132 func (s *ipAddressesStateSuite) ensureMachineDeadAndRemove(c *gc.C, machine *state.Machine) { 133 s.ensureEntityDeadAndRemoved(c, machine) 134 } 135 136 type ensureDeaderRemover interface { 137 state.EnsureDeader 138 state.Remover 139 } 140 141 func (s *ipAddressesStateSuite) ensureEntityDeadAndRemoved(c *gc.C, entity ensureDeaderRemover) { 142 err := entity.EnsureDead() 143 c.Assert(err, jc.ErrorIsNil) 144 err = entity.Remove() 145 c.Assert(err, jc.ErrorIsNil) 146 } 147 148 func (s *ipAddressesStateSuite) TestDeviceMethodReturnsLinkLayerDevice(c *gc.C) { 149 addedDevice, addresses := s.addNamedDeviceWithAddresses(c, "eth0", "0.1.2.3/24") 150 151 returnedDevice, err := addresses[0].Device() 152 c.Assert(err, jc.ErrorIsNil) 153 c.Assert(returnedDevice, jc.DeepEquals, addedDevice) 154 } 155 156 func (s *ipAddressesStateSuite) TestDeviceMethodReturnsNotFoundErrorWhenMissing(c *gc.C) { 157 device, addresses := s.addNamedDeviceWithAddresses(c, "eth0", "0.1.2.3/24") 158 err := device.Remove() 159 c.Assert(err, jc.ErrorIsNil) 160 161 result, err := addresses[0].Device() 162 c.Assert(result, gc.IsNil) 163 c.Assert(err, jc.Satisfies, errors.IsNotFound) 164 c.Assert(err, gc.ErrorMatches, `device with ID .+ not found`) 165 } 166 167 func (s *ipAddressesStateSuite) TestSubnetMethodReturnsSubnet(c *gc.C) { 168 _, addresses := s.addNamedDeviceWithAddresses(c, "eth0", "10.20.30.41/16") 169 170 result, err := addresses[0].Subnet() 171 c.Assert(err, jc.ErrorIsNil) 172 c.Assert(result.CIDR(), gc.Equals, "10.20.0.0/16") 173 } 174 175 func (s *ipAddressesStateSuite) TestSubnetMethodReturnsNotFoundErrorWhenMissing(c *gc.C) { 176 _, addresses := s.addNamedDeviceWithAddresses(c, "eth0", "10.20.30.41/16") 177 subnet, err := s.State.SubnetByCIDR("10.20.0.0/16") 178 c.Assert(err, jc.ErrorIsNil) 179 s.ensureEntityDeadAndRemoved(c, subnet) 180 181 result, err := addresses[0].Subnet() 182 c.Assert(err, jc.Satisfies, errors.IsNotFound) 183 c.Assert(err, gc.ErrorMatches, `subnet "10.20.0.0/16" not found`) 184 c.Assert(result, gc.IsNil) 185 } 186 187 func (s *ipAddressesStateSuite) TestSubnetMethodReturnsNotFoundErrorWithUnknownOrLocalSubnet(c *gc.C) { 188 cidrs := []string{"127.0.0.0/8", "::1/128", "8.8.0.0/16"} 189 missingCIDRs := set.NewStrings(cidrs...) 190 _, addresses := s.addNamedDeviceWithAddresses(c, "eth0", cidrs...) 191 192 for _, address := range addresses { 193 result, err := address.Subnet() 194 c.Check(result, gc.IsNil) 195 c.Check(err, jc.Satisfies, errors.IsNotFound) 196 expectedError := fmt.Sprintf("subnet %q not found", address.SubnetCIDR()) 197 c.Check(err, gc.ErrorMatches, expectedError) 198 missingCIDRs.Remove(address.SubnetCIDR()) 199 } 200 c.Check(missingCIDRs.SortedValues(), gc.DeepEquals, []string{}) 201 } 202 203 func (s *ipAddressesStateSuite) TestRemoveSuccess(c *gc.C) { 204 _, existingAddresses := s.addNamedDeviceWithAddresses(c, "eth0", "0.1.2.3/24") 205 206 s.removeAddressAndAssertSuccess(c, existingAddresses[0]) 207 s.assertNoAddressesOnMachine(c, s.machine) 208 } 209 210 func (s *ipAddressesStateSuite) removeAddressAndAssertSuccess(c *gc.C, givenAddress *state.Address) { 211 err := givenAddress.Remove() 212 c.Assert(err, jc.ErrorIsNil) 213 } 214 215 func (s *ipAddressesStateSuite) assertNoAddressesOnMachine(c *gc.C, machine *state.Machine) { 216 s.assertAllAddressesOnMachineMatchCount(c, machine, 0) 217 } 218 219 func (s *ipAddressesStateSuite) assertAllAddressesOnMachineMatchCount( 220 c *gc.C, machine *state.Machine, expectedCount int, 221 ) { 222 results, err := machine.AllDeviceAddresses() 223 c.Assert(err, jc.ErrorIsNil) 224 c.Assert(results, gc.HasLen, expectedCount, gc.Commentf( 225 "expected %d, got %d: %+v", expectedCount, len(results), results)) 226 } 227 228 func (s *ipAddressesStateSuite) TestRemoveTwiceStillSucceeds(c *gc.C) { 229 _, existingAddresses := s.addNamedDeviceWithAddresses(c, "eth0", "0.1.2.3/24") 230 231 s.removeAddressAndAssertSuccess(c, existingAddresses[0]) 232 s.removeAddressAndAssertSuccess(c, existingAddresses[0]) 233 s.assertNoAddressesOnMachine(c, s.machine) 234 } 235 236 func (s *ipAddressesStateSuite) TestLinkLayerDeviceAddressesReturnsAllDeviceAddresses(c *gc.C) { 237 device, addedAddresses := s.addNamedDeviceWithAddresses(c, "eth0", "0.1.2.3/24", "10.20.30.40/16", "fc00::/64") 238 s.assertAllAddressesOnMachineMatchCount(c, s.machine, 3) 239 240 resultAddresses, err := device.Addresses() 241 c.Assert(err, jc.ErrorIsNil) 242 c.Assert(resultAddresses, jc.DeepEquals, addedAddresses) 243 } 244 245 func (s *ipAddressesStateSuite) TestLinkLayerDeviceRemoveAddressesSuccess(c *gc.C) { 246 device, _ := s.addNamedDeviceWithAddresses(c, "eth0", "10.20.30.40/16", "fc00::/64") 247 s.assertAllAddressesOnMachineMatchCount(c, s.machine, 2) 248 249 s.removeDeviceAddressesAndAssertNoneRemainOnMachine(c, device) 250 } 251 252 func (s *ipAddressesStateSuite) removeDeviceAddressesAndAssertNoneRemainOnMachine( 253 c *gc.C, device *state.LinkLayerDevice, 254 ) { 255 err := device.RemoveAddresses() 256 c.Assert(err, jc.ErrorIsNil) 257 s.assertNoAddressesOnMachine(c, s.machine) 258 } 259 260 func (s *ipAddressesStateSuite) TestLinkLayerDeviceRemoveAddressesTwiceStillSucceeds(c *gc.C) { 261 device, _ := s.addNamedDeviceWithAddresses(c, "eth0", "10.20.30.40/16", "fc00::/64") 262 s.assertAllAddressesOnMachineMatchCount(c, s.machine, 2) 263 264 s.removeDeviceAddressesAndAssertNoneRemainOnMachine(c, device) 265 s.removeDeviceAddressesAndAssertNoneRemainOnMachine(c, device) 266 } 267 268 func (s *ipAddressesStateSuite) TestMachineRemoveAllAddressesSuccess(c *gc.C) { 269 s.addTwoDevicesWithTwoAddressesEach(c) 270 s.removeAllAddressesOnMachineAndAssertNoneRemain(c) 271 } 272 273 func (s *ipAddressesStateSuite) TestMachineRemoveAllAddressesRemovesProviderIDReferences(c *gc.C) { 274 s.addNamedDevice(c, "foo") 275 addrArgs := state.LinkLayerDeviceAddress{ 276 DeviceName: "foo", 277 ConfigMethod: network.ConfigStatic, 278 CIDRAddress: "0.1.2.3/24", 279 ProviderID: "bar", 280 } 281 err := s.machine.SetDevicesAddresses(addrArgs) 282 c.Assert(err, jc.ErrorIsNil) 283 s.removeAllAddressesOnMachineAndAssertNoneRemain(c) 284 285 // Re-adding the same address to a new device should now succeed. 286 err = s.machine.SetDevicesAddresses(addrArgs) 287 c.Assert(err, jc.ErrorIsNil) 288 } 289 290 func (s *ipAddressesStateSuite) addTwoDevicesWithTwoAddressesEach(c *gc.C) []*state.Address { 291 _, device1Addresses := s.addNamedDeviceWithAddresses(c, "eth1", "10.20.0.1/16", "10.20.0.2/16") 292 _, device2Addresses := s.addNamedDeviceWithAddresses(c, "eth0", "10.20.100.2/16", "fc00::/64") 293 s.assertAllAddressesOnMachineMatchCount(c, s.machine, 4) 294 addresses := append(device1Addresses, device2Addresses...) 295 sort.Sort(AddressSorter(addresses)) 296 return addresses 297 } 298 299 func (s *ipAddressesStateSuite) removeAllAddressesOnMachineAndAssertNoneRemain(c *gc.C) { 300 err := s.machine.RemoveAllAddresses() 301 c.Assert(err, jc.ErrorIsNil) 302 s.assertNoAddressesOnMachine(c, s.machine) 303 } 304 305 func (s *ipAddressesStateSuite) TestMachineRemoveAllAddressesTwiceStillSucceeds(c *gc.C) { 306 s.addTwoDevicesWithTwoAddressesEach(c) 307 s.removeAllAddressesOnMachineAndAssertNoneRemain(c) 308 s.removeAllAddressesOnMachineAndAssertNoneRemain(c) 309 } 310 311 func (s *ipAddressesStateSuite) TestMachineAllAddressesSuccess(c *gc.C) { 312 addedAddresses := s.addTwoDevicesWithTwoAddressesEach(c) 313 314 allAddresses, err := s.machine.AllDeviceAddresses() 315 sort.Sort(AddressSorter(allAddresses)) 316 c.Assert(err, jc.ErrorIsNil) 317 c.Assert(allAddresses, jc.DeepEquals, addedAddresses) 318 } 319 320 func (s *ipAddressesStateSuite) TestLinkLayerDeviceRemoveAlsoRemovesDeviceAddresses(c *gc.C) { 321 device, _ := s.addNamedDeviceWithAddresses(c, "eth0", "10.20.30.40/16", "fc00::/64") 322 s.assertAllAddressesOnMachineMatchCount(c, s.machine, 2) 323 324 err := device.Remove() 325 c.Assert(err, jc.ErrorIsNil) 326 s.assertNoAddressesOnMachine(c, s.machine) 327 } 328 329 func (s *ipAddressesStateSuite) TestMachineRemoveAlsoRemovesAllAddresses(c *gc.C) { 330 s.addTwoDevicesWithTwoAddressesEach(c) 331 s.ensureMachineDeadAndRemove(c, s.machine) 332 s.assertNoAddressesOnMachine(c, s.machine) 333 } 334 335 func (s *ipAddressesStateSuite) TestAllSpacesHandlesUnknownSubnets(c *gc.C) { 336 // This is not one of the registered subnets 337 s.addNamedDeviceWithAddresses(c, "eth0", "172.12.0.10/24") 338 spaces, err := s.machine.AllSpaces() 339 c.Assert(err, jc.ErrorIsNil) 340 c.Check(spaces.SortedValues(), gc.DeepEquals, []string{}) 341 } 342 343 func resetSubnet(c *gc.C, st *state.State, subnetInfo network.SubnetInfo) { 344 // TODO (hml) 2019-07-26 345 // This comment is no longer valid. Changes are in progress. 346 // Update when complete. 347 // 348 // We currently don't allow updating a subnet's information, so remove it 349 // and add it with the new value. 350 // XXX(jam): We should add mutation operations instead of this ugly hack 351 subnet, err := st.SubnetByCIDR(subnetInfo.CIDR) 352 c.Assert(err, jc.ErrorIsNil) 353 err = subnet.EnsureDead() 354 c.Assert(err, jc.ErrorIsNil) 355 err = subnet.Remove() 356 c.Assert(err, jc.ErrorIsNil) 357 _, err = st.AddSubnet(subnetInfo) 358 c.Assert(err, jc.ErrorIsNil) 359 } 360 361 func (s *ipAddressesStateSuite) TestAllSpacesOneSpace(c *gc.C) { 362 s.addTwoDevicesWithTwoAddressesEach(c) 363 space, err := s.State.AddSpace("default", "default", nil, true) 364 c.Assert(err, jc.ErrorIsNil) 365 resetSubnet(c, s.State, network.SubnetInfo{ 366 CIDR: "10.20.0.0/16", 367 SpaceID: space.Id(), 368 }) 369 c.Assert(err, jc.ErrorIsNil) 370 resetSubnet(c, s.State, network.SubnetInfo{ 371 CIDR: "fc00::/64", 372 SpaceID: space.Id(), 373 }) 374 c.Assert(err, jc.ErrorIsNil) 375 spaces, err := s.machine.AllSpaces() 376 c.Assert(err, jc.ErrorIsNil) 377 c.Check(spaces.SortedValues(), gc.DeepEquals, []string{space.Id()}) 378 } 379 380 func (s *ipAddressesStateSuite) TestAllSpacesMultiSpace(c *gc.C) { 381 s.addTwoDevicesWithTwoAddressesEach(c) 382 space1, err := s.State.AddSpace("default", "default", nil, true) 383 c.Assert(err, jc.ErrorIsNil) 384 resetSubnet(c, s.State, network.SubnetInfo{ 385 CIDR: "10.20.0.0/16", 386 SpaceID: space1.Id(), 387 }) 388 c.Assert(err, jc.ErrorIsNil) 389 space2, err := s.State.AddSpace("dmz-ipv6", "not-default", nil, true) 390 c.Assert(err, jc.ErrorIsNil) 391 resetSubnet(c, s.State, network.SubnetInfo{ 392 CIDR: "fc00::/64", 393 SpaceID: space2.Id(), 394 }) 395 c.Assert(err, jc.ErrorIsNil) 396 spaces, err := s.machine.AllSpaces() 397 c.Assert(err, jc.ErrorIsNil) 398 c.Check(spaces.SortedValues(), gc.DeepEquals, []string{space1.Id(), space2.Id()}) 399 } 400 401 func (s *ipAddressesStateSuite) TestAllSpacesReturnsDefaultSpace(c *gc.C) { 402 s.addTwoDevicesWithTwoAddressesEach(c) 403 spaces, err := s.machine.AllSpaces() 404 c.Assert(err, jc.ErrorIsNil) 405 c.Check(spaces.SortedValues(), gc.DeepEquals, []string{network.AlphaSpaceId}) 406 } 407 408 func (s *ipAddressesStateSuite) TestSetDevicesAddressesDoesNothingWithEmptyArgs(c *gc.C) { 409 err := s.machine.SetDevicesAddresses() // takes varargs, which includes none. 410 c.Assert(err, jc.ErrorIsNil) 411 } 412 413 func (s *ipAddressesStateSuite) TestSetDevicesAddressesFailsWithEmptyCIDRAddress(c *gc.C) { 414 args := state.LinkLayerDeviceAddress{} 415 s.assertSetDevicesAddressesFailsValidationForArgs(c, args, "empty CIDRAddress not valid") 416 } 417 418 func (s *ipAddressesStateSuite) assertSetDevicesAddressesFailsValidationForArgs( 419 c *gc.C, args state.LinkLayerDeviceAddress, errorCauseMatches string, 420 ) { 421 invalidAddressPrefix := fmt.Sprintf("invalid address %q: ", args.CIDRAddress) 422 err := s.assertSetDevicesAddressesFailsForArgs(c, args, invalidAddressPrefix+errorCauseMatches) 423 c.Assert(err, jc.Satisfies, errors.IsNotValid) 424 } 425 426 func (s *ipAddressesStateSuite) assertSetDevicesAddressesFailsForArgs( 427 c *gc.C, args state.LinkLayerDeviceAddress, errorCauseMatches string, 428 ) error { 429 err := s.machine.SetDevicesAddresses(args) 430 expectedError := fmt.Sprintf( 431 "cannot set link-layer device addresses of machine %q: %s", s.machine.Id(), errorCauseMatches) 432 c.Assert(err, gc.ErrorMatches, expectedError) 433 return err 434 } 435 436 func (s *ipAddressesStateSuite) TestSetDevicesAddressesFailsWithInvalidCIDRAddress(c *gc.C) { 437 args := state.LinkLayerDeviceAddress{ 438 CIDRAddress: "bad CIDR", 439 } 440 s.assertSetDevicesAddressesFailsValidationForArgs(c, args, "CIDRAddress: invalid CIDR address: bad CIDR") 441 } 442 443 func (s *ipAddressesStateSuite) TestSetDevicesAddressesFailsWithCIDRAddressWithoutMask(c *gc.C) { 444 args := state.LinkLayerDeviceAddress{ 445 CIDRAddress: "10.10.10.10", 446 } 447 s.assertSetDevicesAddressesFailsValidationForArgs(c, args, "CIDRAddress: invalid CIDR address: 10.10.10.10") 448 } 449 450 func (s *ipAddressesStateSuite) TestSetDevicesAddressesFailsWithEmptyDeviceName(c *gc.C) { 451 args := state.LinkLayerDeviceAddress{ 452 CIDRAddress: "0.1.2.3/24", 453 } 454 s.assertSetDevicesAddressesFailsValidationForArgs(c, args, "empty DeviceName not valid") 455 } 456 457 func (s *ipAddressesStateSuite) TestSetDevicesAddressesFailsWithUnknownDeviceName(c *gc.C) { 458 args := state.LinkLayerDeviceAddress{ 459 CIDRAddress: "0.1.2.3/24", 460 ConfigMethod: network.ConfigStatic, 461 DeviceName: "missing", 462 } 463 expectedError := `invalid address "0.1.2.3/24": DeviceName "missing" on machine "0" not found` 464 err := s.assertSetDevicesAddressesFailsForArgs(c, args, expectedError) 465 c.Assert(err, jc.Satisfies, errors.IsNotFound) 466 } 467 468 func (s *ipAddressesStateSuite) TestSetDevicesAddressesFailsWithInvalidGatewayAddress(c *gc.C) { 469 s.addNamedDevice(c, "eth0") 470 args := state.LinkLayerDeviceAddress{ 471 CIDRAddress: "0.1.2.3/24", 472 DeviceName: "eth0", 473 ConfigMethod: network.ConfigStatic, 474 GatewayAddress: "boo hoo", 475 } 476 s.assertSetDevicesAddressesFailsValidationForArgs(c, args, `GatewayAddress "boo hoo" not valid`) 477 } 478 479 func (s *ipAddressesStateSuite) TestSetDevicesAddressesOKWhenCIDRAddressDoesNotMatchKnownSubnet(c *gc.C) { 480 device := s.addNamedDevice(c, "eth0") 481 args := state.LinkLayerDeviceAddress{ 482 CIDRAddress: "192.168.123.42/16", 483 DeviceName: "eth0", 484 ConfigMethod: network.ConfigStatic, 485 } 486 err := s.machine.SetDevicesAddresses(args) 487 c.Assert(err, jc.ErrorIsNil) 488 489 assertDeviceHasOneAddressWithSubnetCIDREquals := func(subnetCIDR string) { 490 addresses, err := device.Addresses() 491 c.Assert(err, jc.ErrorIsNil) 492 c.Assert(addresses, gc.HasLen, 1) 493 c.Assert(addresses[0].SubnetCIDR(), gc.Equals, subnetCIDR) 494 } 495 assertDeviceHasOneAddressWithSubnetCIDREquals("192.168.0.0/16") 496 497 // Add the subnet so it's known and retry setting the same address to verify 498 // SubnetID gets updated. 499 _, err = s.State.AddSubnet(network.SubnetInfo{CIDR: "192.168.0.0/16"}) 500 c.Assert(err, jc.ErrorIsNil) 501 err = s.machine.SetDevicesAddresses(args) 502 c.Assert(err, jc.ErrorIsNil) 503 504 assertDeviceHasOneAddressWithSubnetCIDREquals("192.168.0.0/16") 505 } 506 507 func (s *ipAddressesStateSuite) TestSetDevicesAddressesFailsWhenCIDRAddressMatchesDeadSubnet(c *gc.C) { 508 s.addNamedDevice(c, "eth0") 509 subnetCIDR := "10.20.0.0/16" 510 subnet, err := s.State.SubnetByCIDR(subnetCIDR) 511 c.Assert(err, jc.ErrorIsNil) 512 err = subnet.EnsureDead() 513 c.Assert(err, jc.ErrorIsNil) 514 515 args := state.LinkLayerDeviceAddress{ 516 CIDRAddress: "10.20.30.40/16", 517 DeviceName: "eth0", 518 ConfigMethod: network.ConfigStatic, 519 } 520 expectedError := fmt.Sprintf( 521 "invalid address %q: subnet %q is not alive", 522 args.CIDRAddress, subnetCIDR, 523 ) 524 _ = s.assertSetDevicesAddressesFailsForArgs(c, args, expectedError) 525 } 526 527 func (s *ipAddressesStateSuite) TestSetDevicesAddressesFailsWhenMachineNotAliveOrGone(c *gc.C) { 528 s.addNamedDeviceForMachine(c, "eth0", s.otherStateMachine) 529 err := s.otherStateMachine.EnsureDead() 530 c.Assert(err, jc.ErrorIsNil) 531 532 args := state.LinkLayerDeviceAddress{ 533 CIDRAddress: "10.20.30.40/16", 534 DeviceName: "eth0", 535 ConfigMethod: network.ConfigStatic, 536 } 537 err = s.otherStateMachine.SetDevicesAddresses(args) 538 c.Assert(err, gc.ErrorMatches, `.*: machine "0" not alive`) 539 540 err = s.otherStateMachine.Remove() 541 c.Assert(err, jc.ErrorIsNil) 542 543 // Check it fails with a different error, as eth0 was removed along with 544 // otherStateMachine above. 545 err = s.otherStateMachine.SetDevicesAddresses(args) 546 c.Assert(err, gc.ErrorMatches, `.*: DeviceName "eth0" on machine "0" not found`) 547 } 548 549 func (s *ipAddressesStateSuite) TestSetDevicesAddressesUpdatesExistingDocs(c *gc.C) { 550 device, initialAddresses := s.addNamedDeviceWithAddresses(c, "eth0", "0.1.2.3/24", "10.20.30.42/16") 551 552 setArgs := []state.LinkLayerDeviceAddress{{ 553 // All fields that can be set are included below. 554 DeviceName: "eth0", 555 ConfigMethod: network.ConfigManual, 556 CIDRAddress: "0.1.2.3/24", 557 ProviderID: "id-0123", 558 DNSServers: []string{"ns1.example.com", "ns2.example.org"}, 559 DNSSearchDomains: []string{"example.com", "example.org"}, 560 GatewayAddress: "0.1.2.1", 561 }, { 562 // No changed fields, just the required values are set: CIDRAddress + 563 // DeviceName (and s.machine.Id) are used to construct the DocID. 564 DeviceName: "eth0", 565 ConfigMethod: network.ConfigStatic, 566 CIDRAddress: "10.20.30.42/16", 567 }} 568 err := s.machine.SetDevicesAddresses(setArgs...) 569 c.Assert(err, jc.ErrorIsNil) 570 updatedAddresses, err := device.Addresses() 571 c.Assert(err, jc.ErrorIsNil) 572 c.Assert(updatedAddresses, gc.HasLen, len(initialAddresses)) 573 if updatedAddresses[0].Value() != "0.1.2.3" { 574 // Swap the results if they arrive in different order. 575 updatedAddresses[1], updatedAddresses[0] = updatedAddresses[0], updatedAddresses[1] 576 } 577 578 for i, address := range updatedAddresses { 579 s.checkAddressMatchesArgs(c, address, setArgs[i]) 580 } 581 } 582 583 func (s *ipAddressesStateSuite) TestRemoveAddressRemovesProviderID(c *gc.C) { 584 device := s.addNamedDevice(c, "eth0") 585 addrArgs := state.LinkLayerDeviceAddress{ 586 DeviceName: "eth0", 587 ConfigMethod: network.ConfigManual, 588 CIDRAddress: "0.1.2.3/24", 589 ProviderID: "id-0123", 590 } 591 err := s.machine.SetDevicesAddresses(addrArgs) 592 c.Assert(err, jc.ErrorIsNil) 593 addresses, err := device.Addresses() 594 c.Assert(err, jc.ErrorIsNil) 595 c.Assert(addresses, gc.HasLen, 1) 596 addr := addresses[0] 597 err = addr.Remove() 598 c.Assert(err, jc.ErrorIsNil) 599 err = s.machine.SetDevicesAddresses(addrArgs) 600 c.Assert(err, jc.ErrorIsNil) 601 } 602 603 func (s *ipAddressesStateSuite) TestChangeOriginOpsNoProviderID(c *gc.C) { 604 dev := s.addNamedDevice(c, "eth0") 605 606 addrArgs := state.LinkLayerDeviceAddress{ 607 DeviceName: "eth0", 608 ConfigMethod: network.ConfigManual, 609 CIDRAddress: "0.1.2.3/24", 610 Origin: network.OriginMachine, 611 } 612 err := s.machine.SetDevicesAddresses(addrArgs) 613 c.Assert(err, jc.ErrorIsNil) 614 615 addrs, err := dev.Addresses() 616 c.Assert(err, jc.ErrorIsNil) 617 addr := addrs[0] 618 c.Assert(addr.Origin(), gc.Equals, network.OriginMachine) 619 620 // No operations for setting the same origin. 621 c.Assert(addr.SetOriginOps(network.OriginMachine), gc.IsNil) 622 623 state.RunTransaction(c, s.State, addr.SetOriginOps(network.OriginProvider)) 624 625 addrs, err = dev.Addresses() 626 c.Assert(err, jc.ErrorIsNil) 627 addr = addrs[0] 628 c.Assert(addr.Origin(), gc.Equals, network.OriginProvider) 629 } 630 631 func (s *ipAddressesStateSuite) TestChangeOriginOpsWithProviderID(c *gc.C) { 632 dev := s.addNamedDevice(c, "eth0") 633 634 addrArgs := state.LinkLayerDeviceAddress{ 635 DeviceName: "eth0", 636 ConfigMethod: network.ConfigManual, 637 CIDRAddress: "0.1.2.3/24", 638 Origin: network.OriginProvider, 639 ProviderID: "p1", 640 } 641 err := s.machine.SetDevicesAddresses(addrArgs) 642 c.Assert(err, jc.ErrorIsNil) 643 644 addrs, err := dev.Addresses() 645 c.Assert(err, jc.ErrorIsNil) 646 addr := addrs[0] 647 c.Assert(addr.Origin(), gc.Equals, network.OriginProvider) 648 649 // No operations for setting the same origin. 650 c.Assert(addr.SetOriginOps(network.OriginProvider), gc.IsNil) 651 652 state.RunTransaction(c, s.State, addr.SetOriginOps(network.OriginMachine)) 653 654 addrs, err = dev.Addresses() 655 c.Assert(err, jc.ErrorIsNil) 656 addr = addrs[0] 657 c.Assert(addr.Origin(), gc.Equals, network.OriginMachine) 658 c.Assert(addr.ProviderID().String(), gc.Equals, "") 659 660 // Set the address again with the provider ID. 661 // Success means the provider ID was removed from the global collection. 662 addrArgs = state.LinkLayerDeviceAddress{ 663 DeviceName: "eth0", 664 ConfigMethod: network.ConfigManual, 665 CIDRAddress: "0.1.2.3/24", 666 Origin: network.OriginProvider, 667 ProviderID: "p1", 668 } 669 err = s.machine.SetDevicesAddresses(addrArgs) 670 c.Assert(err, jc.ErrorIsNil) 671 } 672 673 func (s *ipAddressesStateSuite) TestSetProviderIDOps(c *gc.C) { 674 dev := s.addNamedDevice(c, "eth0") 675 676 addrArgs := state.LinkLayerDeviceAddress{ 677 DeviceName: "eth0", 678 ConfigMethod: network.ConfigManual, 679 CIDRAddress: "0.1.2.3/24", 680 Origin: network.OriginMachine, 681 } 682 err := s.machine.SetDevicesAddresses(addrArgs) 683 c.Assert(err, jc.ErrorIsNil) 684 685 addrs, err := dev.Addresses() 686 c.Assert(err, jc.ErrorIsNil) 687 addr := addrs[0] 688 c.Assert(addr.Origin(), gc.Equals, network.OriginMachine) 689 690 ops, err := addr.SetProviderIDOps("p1") 691 c.Assert(err, jc.ErrorIsNil) 692 693 state.RunTransaction(c, s.State, ops) 694 695 addrs, err = dev.Addresses() 696 c.Assert(err, jc.ErrorIsNil) 697 addr = addrs[0] 698 c.Assert(addr.ProviderID().String(), gc.Equals, "p1") 699 c.Assert(addr.Origin(), gc.Equals, network.OriginProvider) 700 701 // No operations for setting the same ID. 702 _, err = dev.Addresses() 703 c.Assert(err, jc.ErrorIsNil) 704 705 ops, err = addr.SetProviderIDOps("p1") 706 c.Assert(err, jc.ErrorIsNil) 707 c.Assert(ops, gc.HasLen, 0) 708 } 709 710 func (s *ipAddressesStateSuite) TestSetProviderNetIDsOps(c *gc.C) { 711 dev := s.addNamedDevice(c, "eth0") 712 713 addrArgs := state.LinkLayerDeviceAddress{ 714 DeviceName: "eth0", 715 ConfigMethod: network.ConfigManual, 716 CIDRAddress: "0.1.2.3/24", 717 Origin: network.OriginMachine, 718 ProviderNetworkID: "p-net-1", 719 ProviderSubnetID: "p-sub-1", 720 } 721 err := s.machine.SetDevicesAddresses(addrArgs) 722 c.Assert(err, jc.ErrorIsNil) 723 724 addrs, err := dev.Addresses() 725 c.Assert(err, jc.ErrorIsNil) 726 addr := addrs[0] 727 728 ops := addr.SetProviderNetIDsOps("p-net-1", "p-sub-1") 729 c.Assert(ops, gc.HasLen, 0) 730 731 ops = addr.SetProviderNetIDsOps("p-net-2", "p-sub-2") 732 state.RunTransaction(c, s.State, ops) 733 734 addrs, err = dev.Addresses() 735 c.Assert(err, jc.ErrorIsNil) 736 addr = addrs[0] 737 738 c.Assert(addr.ProviderNetworkID().String(), gc.Equals, "p-net-2") 739 c.Assert(addr.ProviderSubnetID().String(), gc.Equals, "p-sub-2") 740 } 741 742 func (s *ipAddressesStateSuite) TestUpdateOps(c *gc.C) { 743 dev := s.addNamedDevice(c, "eth0") 744 745 addrArgs := state.LinkLayerDeviceAddress{ 746 DeviceName: "eth0", 747 ConfigMethod: network.ConfigManual, 748 CIDRAddress: "0.1.2.3/24", 749 Origin: network.OriginMachine, 750 } 751 err := s.machine.SetDevicesAddresses(addrArgs) 752 c.Assert(err, jc.ErrorIsNil) 753 754 addrs, err := dev.Addresses() 755 c.Assert(err, jc.ErrorIsNil) 756 757 ops, err := addrs[0].UpdateOps(state.LinkLayerDeviceAddress{ 758 DeviceName: "eth0", 759 ConfigMethod: network.ConfigManual, 760 CIDRAddress: "0.1.2.3/24", 761 Origin: network.OriginMachine, 762 GatewayAddress: "0.1.2.0", 763 IsSecondary: true, 764 }) 765 c.Assert(err, jc.ErrorIsNil) 766 767 state.RunTransaction(c, s.State, ops) 768 769 addrs, err = dev.Addresses() 770 c.Assert(err, jc.ErrorIsNil) 771 c.Check(addrs[0].GatewayAddress(), gc.Equals, "0.1.2.0") 772 c.Check(addrs[0].IsSecondary(), gc.Equals, true) 773 } 774 775 func (s *ipAddressesStateSuite) TestUpdateAddressFailsToChangeProviderID(c *gc.C) { 776 s.addNamedDevice(c, "eth0") 777 addrArgs := state.LinkLayerDeviceAddress{ 778 DeviceName: "eth0", 779 ConfigMethod: network.ConfigManual, 780 CIDRAddress: "0.1.2.3/24", 781 ProviderID: "id-0123", 782 } 783 err := s.machine.SetDevicesAddresses(addrArgs) 784 c.Assert(err, jc.ErrorIsNil) 785 addrArgs.ProviderID = "id-0124" 786 err = s.machine.SetDevicesAddresses(addrArgs) 787 c.Assert(err, gc.NotNil) 788 } 789 790 func (s *ipAddressesStateSuite) TestUpdateAddressPreventsDuplicateProviderID(c *gc.C) { 791 s.addNamedDevice(c, "eth0") 792 addrArgs := state.LinkLayerDeviceAddress{ 793 DeviceName: "eth0", 794 ConfigMethod: network.ConfigManual, 795 CIDRAddress: "0.1.2.3/24", 796 } 797 err := s.machine.SetDevicesAddresses(addrArgs) 798 c.Assert(err, jc.ErrorIsNil) 799 800 // Set the provider id through an update. 801 addrArgs.ProviderID = "id-0123" 802 err = s.machine.SetDevicesAddresses(addrArgs) 803 c.Assert(err, jc.ErrorIsNil) 804 805 // Adding a new address with the same provider id should now fail. 806 addrArgs.CIDRAddress = "0.1.2.4/24" 807 err = s.machine.SetDevicesAddresses(addrArgs) 808 c.Assert(err, gc.NotNil) 809 } 810 811 func (s *ipAddressesStateSuite) checkAddressMatchesArgs( 812 c *gc.C, address *state.Address, args state.LinkLayerDeviceAddress, 813 ) { 814 c.Check(address.DeviceName(), gc.Equals, args.DeviceName) 815 c.Check(address.MachineID(), gc.Equals, s.machine.Id()) 816 c.Check(args.CIDRAddress, jc.HasPrefix, address.Value()) 817 c.Check(address.ConfigMethod(), gc.Equals, args.ConfigMethod) 818 c.Check(address.ProviderID(), gc.Equals, args.ProviderID) 819 c.Check(address.DNSServers(), jc.DeepEquals, args.DNSServers) 820 c.Check(address.DNSSearchDomains(), jc.DeepEquals, args.DNSSearchDomains) 821 c.Check(address.GatewayAddress(), gc.Equals, args.GatewayAddress) 822 } 823 824 func (s *ipAddressesStateSuite) TestSetDevicesAddressesWithMultipleUpdatesOfSameDocLastUpdateWins(c *gc.C) { 825 device, initialAddresses := s.addNamedDeviceWithAddresses(c, "eth0", "0.1.2.3/24") 826 827 setArgs := []state.LinkLayerDeviceAddress{{ 828 // No changes - same args as used by addNamedDeviceWithAddresses, so 829 // this is testing a no-op case. 830 DeviceName: "eth0", 831 ConfigMethod: network.ConfigStatic, 832 CIDRAddress: "0.1.2.3/24", 833 }, { 834 // Change all fields that can change. 835 DeviceName: "eth0", 836 ConfigMethod: network.ConfigManual, 837 CIDRAddress: "0.1.2.3/24", 838 ProviderID: "id-0123", 839 DNSServers: []string{"ns1.example.com", "ns2.example.org"}, 840 DNSSearchDomains: []string{"example.com", "example.org"}, 841 GatewayAddress: "0.1.2.1", 842 }, { 843 // Test deletes work for DNS settings, also change method, and gateway. 844 DeviceName: "eth0", 845 ConfigMethod: network.ConfigDHCP, 846 CIDRAddress: "0.1.2.3/24", 847 ProviderID: "id-0123", // not allowed to change ProviderID once set 848 DNSServers: nil, 849 DNSSearchDomains: nil, 850 GatewayAddress: "0.1.2.2", 851 }} 852 for _, arg := range setArgs { 853 err := s.machine.SetDevicesAddresses(arg) 854 c.Assert(err, jc.ErrorIsNil) 855 } 856 updatedAddresses, err := device.Addresses() 857 c.Assert(err, jc.ErrorIsNil) 858 c.Assert(updatedAddresses, gc.HasLen, len(initialAddresses)) 859 860 var lastArgsIndex = len(setArgs) - 1 861 s.checkAddressMatchesArgs(c, updatedAddresses[0], state.LinkLayerDeviceAddress{ 862 DeviceName: setArgs[lastArgsIndex].DeviceName, 863 ConfigMethod: setArgs[lastArgsIndex].ConfigMethod, 864 CIDRAddress: setArgs[lastArgsIndex].CIDRAddress, 865 ProviderID: setArgs[lastArgsIndex].ProviderID, 866 DNSServers: setArgs[lastArgsIndex].DNSServers, 867 DNSSearchDomains: setArgs[lastArgsIndex].DNSSearchDomains, 868 GatewayAddress: setArgs[lastArgsIndex].GatewayAddress, 869 }) 870 } 871 872 func (s *ipAddressesStateSuite) TestSetDevicesAddressesMultipleDevicesWithSameAddress(c *gc.C) { 873 _ = s.addNamedDeviceForMachine(c, "eth2", s.machine) 874 _ = s.addNamedDeviceForMachine(c, "br0", s.machine) 875 876 // This is a valid scenario that was observed with a MAAS machine. 877 // eth2 had an address and provider ID managed by MAAS. 878 // eth2 and eth4 were bonded to form bond0. 879 // bond0 was bridged by br0. 880 881 providerID := "42" 882 addressArgs := []state.LinkLayerDeviceAddress{ 883 { 884 DeviceName: "eth2", 885 ConfigMethod: network.ConfigStatic, 886 CIDRAddress: "0.1.2.3/24", 887 ProviderID: network.Id(providerID), 888 }, 889 { 890 DeviceName: "br0", 891 ConfigMethod: network.ConfigStatic, 892 CIDRAddress: "0.1.2.3/24", 893 ProviderID: network.Id(providerID), 894 }, 895 } 896 897 err := s.machine.SetDevicesAddresses(addressArgs...) 898 c.Assert(err, jc.ErrorIsNil) 899 900 // Check that we can still change one of the addresses. 901 addressArgs[0].ConfigMethod = network.ConfigDHCP 902 err = s.machine.SetDevicesAddresses(addressArgs[0]) 903 c.Assert(err, jc.ErrorIsNil) 904 } 905 906 func (s *ipAddressesStateSuite) TestSetDevicesAddressesMultipleDevicesWithSameAddressDifferentProviderIDFails(c *gc.C) { 907 _ = s.addNamedDeviceForMachine(c, "eth2", s.machine) 908 _ = s.addNamedDeviceForMachine(c, "br0", s.machine) 909 910 providerID := "42" 911 addressArgs := []state.LinkLayerDeviceAddress{ 912 { 913 DeviceName: "eth2", 914 ConfigMethod: network.ConfigStatic, 915 CIDRAddress: "0.1.2.3/24", 916 ProviderID: network.Id(providerID), 917 }, 918 { 919 DeviceName: "br0", 920 ConfigMethod: network.ConfigStatic, 921 CIDRAddress: "0.1.2.4/24", 922 ProviderID: network.Id(providerID), 923 }, 924 } 925 926 err := s.machine.SetDevicesAddresses(addressArgs...) 927 c.Assert(err, gc.ErrorMatches, `.*multiple addresses "0.1.2.3", "0.1.2.4": provider IDs not unique: 42`) 928 } 929 930 func (s *ipAddressesStateSuite) TestSetDevicesAddressesWithDuplicateProviderIDFailsInSameModel(c *gc.C) { 931 _, firstAddressArgs := s.addDeviceWithAddressAndProviderIDForMachine(c, "42", s.machine) 932 secondAddressArgs := firstAddressArgs 933 secondAddressArgs.CIDRAddress = "10.20.30.40/16" 934 935 err := s.machine.SetDevicesAddresses(secondAddressArgs) 936 c.Assert(err, gc.NotNil) 937 } 938 939 func (s *ipAddressesStateSuite) TestSetDevicesAddressesWithDuplicateProviderIDSucceedsInDifferentModel(c *gc.C) { 940 _, firstAddressArgs := s.addDeviceWithAddressAndProviderIDForMachine(c, "42", s.otherStateMachine) 941 secondAddressArgs := firstAddressArgs 942 secondAddressArgs.CIDRAddress = "10.20.30.40/16" 943 944 s.addNamedDevice(c, firstAddressArgs.DeviceName) // for s.machine 945 err := s.machine.SetDevicesAddresses(secondAddressArgs) 946 c.Assert(err, jc.ErrorIsNil) 947 } 948 949 func (s *ipAddressesStateSuite) addDeviceWithAddressAndProviderIDForMachine( 950 c *gc.C, providerID string, machine *state.Machine, 951 ) (*state.LinkLayerDevice, state.LinkLayerDeviceAddress) { 952 device := s.addNamedDeviceForMachine(c, "eth0", machine) 953 addressArgs := state.LinkLayerDeviceAddress{ 954 DeviceName: "eth0", 955 ConfigMethod: network.ConfigStatic, 956 CIDRAddress: "0.1.2.3/24", 957 ProviderID: network.Id(providerID), 958 } 959 err := machine.SetDevicesAddresses(addressArgs) 960 c.Assert(err, jc.ErrorIsNil) 961 return device, addressArgs 962 }