github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/state/linklayerdevices_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 9 "github.com/juju/errors" 10 jc "github.com/juju/testing/checkers" 11 jujutxn "github.com/juju/txn/v3" 12 gc "gopkg.in/check.v1" 13 14 "github.com/juju/juju/core/instance" 15 corenetwork "github.com/juju/juju/core/network" 16 "github.com/juju/juju/network" 17 "github.com/juju/juju/network/containerizer" 18 "github.com/juju/juju/state" 19 ) 20 21 // linkLayerDevicesStateSuite contains black-box tests for link-layer network 22 // devices, which include access to mongo. 23 type linkLayerDevicesStateSuite struct { 24 ConnSuite 25 26 machine *state.Machine 27 containerMachine *state.Machine 28 otherState *state.State 29 otherStateMachine *state.Machine 30 31 spaces map[string]corenetwork.SpaceInfo 32 33 bridgePolicy *containerizer.BridgePolicy 34 } 35 36 var _ = gc.Suite(&linkLayerDevicesStateSuite{}) 37 38 func (s *linkLayerDevicesStateSuite) SetUpTest(c *gc.C) { 39 s.ConnSuite.SetUpTest(c) 40 41 var err error 42 s.machine, err = s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 43 c.Assert(err, jc.ErrorIsNil) 44 45 s.otherState = s.NewStateForModelNamed(c, "other-model") 46 s.otherStateMachine, err = s.otherState.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 47 c.Assert(err, jc.ErrorIsNil) 48 49 s.spaces = map[string]corenetwork.SpaceInfo{ 50 corenetwork.AlphaSpaceName: {ID: "0", Name: corenetwork.AlphaSpaceName}, 51 } 52 53 s.bridgePolicy = &containerizer.BridgePolicy{} 54 } 55 56 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesNoArgs(c *gc.C) { 57 err := s.machine.SetLinkLayerDevices() // takes varargs, which includes none. 58 c.Assert(err, jc.ErrorIsNil) 59 } 60 61 func (s *linkLayerDevicesStateSuite) assertSetLinkLayerDevicesFailsValidationForArgs(c *gc.C, args state.LinkLayerDeviceArgs, errorCauseMatches string) error { 62 expectedError := fmt.Sprintf("invalid device %q: %s", args.Name, errorCauseMatches) 63 return s.assertSetLinkLayerDevicesFailsForArgs(c, args, expectedError) 64 } 65 66 func (s *linkLayerDevicesStateSuite) assertSetLinkLayerDevicesFailsForArgs(c *gc.C, args state.LinkLayerDeviceArgs, errorCauseMatches string) error { 67 err := s.machine.SetLinkLayerDevices(args) 68 expectedError := fmt.Sprintf("cannot set link-layer devices to machine %q: %s", s.machine.Id(), errorCauseMatches) 69 c.Assert(err, gc.ErrorMatches, expectedError) 70 return err 71 } 72 73 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesWhenMachineNotAliveOrGone(c *gc.C) { 74 err := s.machine.EnsureDead() 75 c.Assert(err, jc.ErrorIsNil) 76 77 args := state.LinkLayerDeviceArgs{ 78 Name: "eth0", 79 Type: corenetwork.EthernetDevice, 80 } 81 _ = s.assertSetLinkLayerDevicesFailsForArgs(c, args, `machine "0" not alive`) 82 83 err = s.machine.Remove() 84 c.Assert(err, jc.ErrorIsNil) 85 86 _ = s.assertSetLinkLayerDevicesFailsForArgs(c, args, `machine "0" not alive`) 87 } 88 89 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesNoParentSuccess(c *gc.C) { 90 args := state.LinkLayerDeviceArgs{ 91 Name: "eth0.42", 92 MTU: 9000, 93 ProviderID: "eni-42", 94 Type: corenetwork.VLAN8021QDevice, 95 MACAddress: "aa:bb:cc:dd:ee:f0", 96 IsAutoStart: true, 97 IsUp: true, 98 } 99 s.assertSetLinkLayerDevicesSucceedsAndResultMatchesArgs(c, args) 100 } 101 102 func (s *linkLayerDevicesStateSuite) assertSetLinkLayerDevicesSucceedsAndResultMatchesArgs( 103 c *gc.C, 104 args state.LinkLayerDeviceArgs, 105 ) *state.LinkLayerDevice { 106 return s.assertMachineSetLinkLayerDevicesSucceedsAndResultMatchesArgs(c, s.machine, args, s.State.ModelUUID()) 107 } 108 109 func (s *linkLayerDevicesStateSuite) assertMachineSetLinkLayerDevicesSucceedsAndResultMatchesArgs( 110 c *gc.C, 111 machine *state.Machine, 112 args state.LinkLayerDeviceArgs, 113 modelUUID string, 114 ) *state.LinkLayerDevice { 115 err := machine.SetLinkLayerDevices(args) 116 c.Assert(err, jc.ErrorIsNil) 117 result, err := machine.LinkLayerDevice(args.Name) 118 c.Assert(err, jc.ErrorIsNil) 119 c.Assert(result, gc.NotNil) 120 121 s.checkSetDeviceMatchesArgs(c, result, args) 122 s.checkSetDeviceMatchesMachineIDAndModelUUID(c, result, s.machine.Id(), modelUUID) 123 return result 124 } 125 126 func (s *linkLayerDevicesStateSuite) checkSetDeviceMatchesArgs(c *gc.C, setDevice *state.LinkLayerDevice, args state.LinkLayerDeviceArgs) { 127 c.Check(setDevice.Name(), gc.Equals, args.Name) 128 c.Check(setDevice.MTU(), gc.Equals, args.MTU) 129 c.Check(setDevice.ProviderID(), gc.Equals, args.ProviderID) 130 c.Check(setDevice.Type(), gc.Equals, args.Type) 131 c.Check(setDevice.MACAddress(), gc.Equals, args.MACAddress) 132 c.Check(setDevice.IsAutoStart(), gc.Equals, args.IsAutoStart) 133 c.Check(setDevice.IsUp(), gc.Equals, args.IsUp) 134 c.Check(setDevice.ParentName(), gc.Equals, args.ParentName) 135 } 136 137 func (s *linkLayerDevicesStateSuite) checkSetDeviceMatchesMachineIDAndModelUUID(c *gc.C, setDevice *state.LinkLayerDevice, machineID, modelUUID string) { 138 globalKey := fmt.Sprintf("m#%s#d#%s", machineID, setDevice.Name()) 139 c.Check(setDevice.DocID(), gc.Equals, modelUUID+":"+globalKey) 140 c.Check(setDevice.MachineID(), gc.Equals, machineID) 141 } 142 143 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesNoProviderIDSuccess(c *gc.C) { 144 args := state.LinkLayerDeviceArgs{ 145 Name: "eno0", 146 Type: corenetwork.EthernetDevice, 147 } 148 s.assertSetLinkLayerDevicesSucceedsAndResultMatchesArgs(c, args) 149 } 150 151 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesWithDuplicateProviderIDFailsInSameModel(c *gc.C) { 152 args1 := state.LinkLayerDeviceArgs{ 153 Name: "eth0.42", 154 Type: corenetwork.EthernetDevice, 155 ProviderID: "42", 156 } 157 s.assertSetLinkLayerDevicesSucceedsAndResultMatchesArgs(c, args1) 158 159 args2 := args1 160 args2.Name = "br-eth0" 161 err := s.assertSetLinkLayerDevicesFailsValidationForArgs(c, args2, `provider IDs not unique: 42`) 162 c.Assert(err, jc.Satisfies, state.IsProviderIDNotUniqueError) 163 } 164 165 func (s *linkLayerDevicesStateSuite) TestRemoveAllLinkLayerDevicesClearsProviderIDs(c *gc.C) { 166 args1 := state.LinkLayerDeviceArgs{ 167 Name: "eth0.42", 168 Type: corenetwork.EthernetDevice, 169 ProviderID: "42", 170 } 171 s.assertSetLinkLayerDevicesSucceedsAndResultMatchesArgs(c, args1) 172 173 c.Assert(s.machine.RemoveAllLinkLayerDevices(), jc.ErrorIsNil) 174 175 // We can add the same device, with the same provider ID without error 176 // because the global provider ID references were removed with the devices. 177 s.assertSetLinkLayerDevicesSucceedsAndResultMatchesArgs(c, args1) 178 } 179 180 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesWithDuplicateNameAndProviderIDSucceedsInDifferentModels(c *gc.C) { 181 args := state.LinkLayerDeviceArgs{ 182 Name: "eth0.42", 183 Type: corenetwork.EthernetDevice, 184 ProviderID: "42", 185 } 186 s.assertSetLinkLayerDevicesSucceedsAndResultMatchesArgs(c, args) 187 188 s.assertMachineSetLinkLayerDevicesSucceedsAndResultMatchesArgs(c, s.otherStateMachine, args, s.otherState.ModelUUID()) 189 } 190 191 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesUpdatesProviderIDWhenNotSetOriginally(c *gc.C) { 192 args := state.LinkLayerDeviceArgs{ 193 Name: "foo", 194 Type: corenetwork.EthernetDevice, 195 } 196 s.assertSetLinkLayerDevicesSucceedsAndResultMatchesArgs(c, args) 197 198 args.ProviderID = "42" 199 s.assertSetLinkLayerDevicesSucceedsAndResultMatchesArgs(c, args) 200 } 201 202 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesUpdateWithDuplicateProviderIDFails(c *gc.C) { 203 args := state.LinkLayerDeviceArgs{ 204 Name: "foo", 205 Type: corenetwork.EthernetDevice, 206 ProviderID: "42", 207 } 208 s.assertSetLinkLayerDevicesSucceedsAndResultMatchesArgs(c, args) 209 args.Name = "bar" 210 args.ProviderID = "" 211 s.assertSetLinkLayerDevicesSucceedsAndResultMatchesArgs(c, args) 212 213 args.ProviderID = "42" 214 err := s.assertSetLinkLayerDevicesFailsValidationForArgs(c, args, `provider IDs not unique: 42`) 215 c.Assert(err, jc.Satisfies, state.IsProviderIDNotUniqueError) 216 } 217 218 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesDoesNotClearProviderIDOnceSet(c *gc.C) { 219 args := state.LinkLayerDeviceArgs{ 220 Name: "foo", 221 Type: corenetwork.EthernetDevice, 222 ProviderID: "42", 223 } 224 s.assertSetLinkLayerDevicesSucceedsAndResultMatchesArgs(c, args) 225 226 args.ProviderID = "" 227 err := s.machine.SetLinkLayerDevices(args) 228 c.Assert(err, jc.ErrorIsNil) 229 device, err := s.machine.LinkLayerDevice(args.Name) 230 c.Assert(err, jc.ErrorIsNil) 231 c.Assert(device.ProviderID(), gc.Equals, corenetwork.Id("42")) 232 } 233 234 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesMultipleArgsWithSameNameFails(c *gc.C) { 235 foo1 := state.LinkLayerDeviceArgs{ 236 Name: "foo", 237 Type: corenetwork.BridgeDevice, 238 } 239 foo2 := state.LinkLayerDeviceArgs{ 240 Name: "foo", 241 Type: corenetwork.EthernetDevice, 242 } 243 err := s.machine.SetLinkLayerDevices(foo1, foo2) 244 c.Assert(err, gc.ErrorMatches, `.*invalid device "foo": Name specified more than once`) 245 c.Assert(err, jc.Satisfies, errors.IsNotValid) 246 } 247 248 func (s *linkLayerDevicesStateSuite) setMultipleDevicesSucceedsAndCheckAllAdded(c *gc.C, allArgs []state.LinkLayerDeviceArgs) []*state.LinkLayerDevice { 249 err := s.machine.SetLinkLayerDevices(allArgs...) 250 c.Assert(err, jc.ErrorIsNil) 251 252 var results []*state.LinkLayerDevice 253 machineID, modelUUID := s.machine.Id(), s.State.ModelUUID() 254 for _, args := range allArgs { 255 device, err := s.machine.LinkLayerDevice(args.Name) 256 c.Check(err, jc.ErrorIsNil) 257 s.checkSetDeviceMatchesArgs(c, device, args) 258 s.checkSetDeviceMatchesMachineIDAndModelUUID(c, device, machineID, modelUUID) 259 results = append(results, device) 260 } 261 return results 262 } 263 264 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesMultipleChildrenOfExistingParentSucceeds(c *gc.C) { 265 s.addNamedParentDeviceWithChildrenAndCheckAllAdded(c, "parent", "child1", "child2") 266 } 267 268 func (s *linkLayerDevicesStateSuite) addNamedParentDeviceWithChildrenAndCheckAllAdded(c *gc.C, parentName string, childrenNames ...string) ( 269 parent *state.LinkLayerDevice, 270 children []*state.LinkLayerDevice, 271 ) { 272 parent = s.addNamedDevice(c, parentName) 273 childrenArgs := make([]state.LinkLayerDeviceArgs, len(childrenNames)) 274 for i, childName := range childrenNames { 275 childrenArgs[i] = state.LinkLayerDeviceArgs{ 276 Name: childName, 277 Type: corenetwork.EthernetDevice, 278 ParentName: parentName, 279 } 280 } 281 282 children = s.setMultipleDevicesSucceedsAndCheckAllAdded(c, childrenArgs) 283 return parent, children 284 } 285 286 func (s *linkLayerDevicesStateSuite) addSimpleDevice(c *gc.C) *state.LinkLayerDevice { 287 return s.addNamedDevice(c, "foo") 288 } 289 290 func (s *linkLayerDevicesStateSuite) addNamedDevice(c *gc.C, name string) *state.LinkLayerDevice { 291 args := state.LinkLayerDeviceArgs{ 292 Name: name, 293 Type: corenetwork.EthernetDevice, 294 } 295 ops, err := s.machine.AddLinkLayerDeviceOps(args) 296 c.Assert(err, jc.ErrorIsNil) 297 state.RunTransaction(c, s.State, ops) 298 299 device, err := s.machine.LinkLayerDevice(name) 300 c.Assert(err, jc.ErrorIsNil) 301 return device 302 } 303 304 func (s *linkLayerDevicesStateSuite) TestMachineMethodReturnsNotFoundErrorWhenMissing(c *gc.C) { 305 device := s.addSimpleDevice(c) 306 307 err := s.machine.EnsureDead() 308 c.Assert(err, jc.ErrorIsNil) 309 err = s.machine.Remove() 310 c.Assert(err, jc.ErrorIsNil) 311 312 result, err := device.Machine() 313 c.Assert(err, gc.ErrorMatches, "machine 0 not found") 314 c.Assert(err, jc.Satisfies, errors.IsNotFound) 315 c.Assert(result, gc.IsNil) 316 } 317 318 func (s *linkLayerDevicesStateSuite) TestMachineMethodReturnsMachine(c *gc.C) { 319 device := s.addSimpleDevice(c) 320 321 result, err := device.Machine() 322 c.Assert(err, jc.ErrorIsNil) 323 c.Assert(result, jc.DeepEquals, s.machine) 324 } 325 326 func (s *linkLayerDevicesStateSuite) TestParentDeviceReturnsLinkLayerDevice(c *gc.C) { 327 parent, children := s.addNamedParentDeviceWithChildrenAndCheckAllAdded(c, "br-eth0", "eth0") 328 329 child := children[0] 330 parentCopy, err := child.ParentDevice() 331 c.Assert(err, jc.ErrorIsNil) 332 c.Assert(parentCopy, jc.DeepEquals, parent) 333 } 334 335 func (s *linkLayerDevicesStateSuite) TestMachineLinkLayerDeviceReturnsNotFoundErrorWhenMissing(c *gc.C) { 336 result, err := s.machine.LinkLayerDevice("missing") 337 c.Assert(result, gc.IsNil) 338 c.Assert(err, jc.Satisfies, errors.IsNotFound) 339 c.Assert(err, gc.ErrorMatches, "device with ID .+ not found") 340 } 341 342 func (s *linkLayerDevicesStateSuite) TestMachineLinkLayerDeviceReturnsLinkLayerDevice(c *gc.C) { 343 existingDevice := s.addSimpleDevice(c) 344 345 result, err := s.machine.LinkLayerDevice(existingDevice.Name()) 346 c.Assert(err, jc.ErrorIsNil) 347 c.Assert(result, jc.DeepEquals, existingDevice) 348 } 349 350 func (s *linkLayerDevicesStateSuite) TestMachineAllLinkLayerDevices(c *gc.C) { 351 s.assertNoDevicesOnMachine(c, s.machine) 352 topParent, secondLevelParents := s.addNamedParentDeviceWithChildrenAndCheckAllAdded(c, "br-bond0", "bond0") 353 secondLevelParent := secondLevelParents[0] 354 355 secondLevelChildrenArgs := []state.LinkLayerDeviceArgs{{ 356 Name: "eth0", 357 Type: corenetwork.EthernetDevice, 358 ParentName: secondLevelParent.Name(), 359 }, { 360 Name: "eth1", 361 Type: corenetwork.EthernetDevice, 362 ParentName: secondLevelParent.Name(), 363 }} 364 s.setMultipleDevicesSucceedsAndCheckAllAdded(c, secondLevelChildrenArgs) 365 366 results, err := s.machine.AllLinkLayerDevices() 367 c.Assert(err, jc.ErrorIsNil) 368 c.Assert(results, gc.HasLen, 4) 369 for _, result := range results { 370 c.Check(result, gc.NotNil) 371 c.Check(result.MachineID(), gc.Equals, s.machine.Id()) 372 c.Check(result.Name(), gc.Matches, `(br-bond0|bond0|eth0|eth1)`) 373 if result.Name() == topParent.Name() { 374 c.Check(result.ParentName(), gc.Equals, "") 375 continue 376 } 377 c.Check(result.ParentName(), gc.Matches, `(br-bond0|bond0)`) 378 } 379 } 380 381 func (s *linkLayerDevicesStateSuite) TestMachineAllProviderInterfaceInfos(c *gc.C) { 382 err := s.machine.SetLinkLayerDevices(state.LinkLayerDeviceArgs{ 383 Name: "sara-lynn", 384 MACAddress: "ab:cd:ef:01:23:45", 385 ProviderID: "thing1", 386 Type: corenetwork.EthernetDevice, 387 }, state.LinkLayerDeviceArgs{ 388 Name: "bojack", 389 MACAddress: "ab:cd:ef:01:23:46", 390 ProviderID: "thing2", 391 Type: corenetwork.EthernetDevice, 392 }) 393 c.Assert(err, jc.ErrorIsNil) 394 395 results, err := s.machine.AllProviderInterfaceInfos() 396 c.Assert(err, jc.ErrorIsNil) 397 c.Assert(results, jc.SameContents, []corenetwork.ProviderInterfaceInfo{{ 398 InterfaceName: "sara-lynn", 399 HardwareAddress: "ab:cd:ef:01:23:45", 400 ProviderId: "thing1", 401 }, { 402 InterfaceName: "bojack", 403 HardwareAddress: "ab:cd:ef:01:23:46", 404 ProviderId: "thing2", 405 }}) 406 } 407 408 func (s *linkLayerDevicesStateSuite) assertNoDevicesOnMachine(c *gc.C, machine *state.Machine) { 409 s.assertAllLinkLayerDevicesOnMachineMatchCount(c, machine, 0) 410 } 411 412 func (s *linkLayerDevicesStateSuite) assertAllLinkLayerDevicesOnMachineMatchCount(c *gc.C, machine *state.Machine, expectedCount int) { 413 results, err := machine.AllLinkLayerDevices() 414 c.Assert(err, jc.ErrorIsNil) 415 c.Assert(results, gc.HasLen, expectedCount) 416 } 417 418 func (s *linkLayerDevicesStateSuite) TestMachineAllLinkLayerDevicesOnlyReturnsSameModelDevices(c *gc.C) { 419 s.assertNoDevicesOnMachine(c, s.machine) 420 s.assertNoDevicesOnMachine(c, s.otherStateMachine) 421 422 s.addNamedParentDeviceWithChildrenAndCheckAllAdded(c, "foo", "foo.42") 423 424 results, err := s.machine.AllLinkLayerDevices() 425 c.Assert(err, jc.ErrorIsNil) 426 c.Assert(results, gc.HasLen, 2) 427 428 deviceNames := make([]string, 2) 429 for i, res := range results { 430 deviceNames[i] = res.Name() 431 } 432 c.Assert(deviceNames, jc.SameContents, []string{"foo", "foo.42"}) 433 434 s.assertNoDevicesOnMachine(c, s.otherStateMachine) 435 } 436 437 func (s *linkLayerDevicesStateSuite) TestLinkLayerDeviceRemoveFailsWithExistingChildren(c *gc.C) { 438 parent, _ := s.addNamedParentDeviceWithChildrenAndCheckAllAdded(c, "parent", "one-child", "another-child") 439 440 err := parent.Remove() 441 expectedError := fmt.Sprintf( 442 "cannot remove %s: parent device %q has 2 children", 443 parent, parent.Name(), 444 ) 445 c.Assert(err, gc.ErrorMatches, expectedError) 446 c.Assert(err, jc.Satisfies, state.IsParentDeviceHasChildrenError) 447 } 448 449 func (s *linkLayerDevicesStateSuite) TestLinkLayerParentRemoveOKAfterChangingChildrensToNewParent(c *gc.C) { 450 originalParent, children := s.addNamedParentDeviceWithChildrenAndCheckAllAdded(c, "parent", "one-child", "another-child") 451 newParent := s.addNamedDevice(c, "new-parent") 452 453 updateArgs := []state.LinkLayerDeviceArgs{{ 454 Name: children[0].Name(), 455 Type: children[0].Type(), 456 ParentName: newParent.Name(), 457 }, { 458 Name: children[1].Name(), 459 Type: children[1].Type(), 460 ParentName: newParent.Name(), 461 }} 462 err := s.machine.SetLinkLayerDevices(updateArgs...) 463 c.Assert(err, jc.ErrorIsNil) 464 465 err = originalParent.Remove() 466 c.Assert(err, jc.ErrorIsNil) 467 468 err = newParent.Remove() 469 expectedError := fmt.Sprintf( 470 "cannot remove %s: parent device %q has 2 children", 471 newParent, newParent.Name(), 472 ) 473 c.Assert(err, gc.ErrorMatches, expectedError) 474 c.Assert(err, jc.Satisfies, state.IsParentDeviceHasChildrenError) 475 } 476 477 func (s *linkLayerDevicesStateSuite) TestLinkLayerDeviceRemoveSuccess(c *gc.C) { 478 existingDevice := s.addSimpleDevice(c) 479 480 s.removeDeviceAndAssertSuccess(c, existingDevice) 481 s.assertNoDevicesOnMachine(c, s.machine) 482 } 483 484 func (s *linkLayerDevicesStateSuite) TestLinkLayerDeviceRemoveRemovesProviderID(c *gc.C) { 485 args := state.LinkLayerDeviceArgs{ 486 Name: "foo", 487 Type: corenetwork.EthernetDevice, 488 ProviderID: "bar", 489 } 490 err := s.machine.SetLinkLayerDevices(args) 491 c.Assert(err, jc.ErrorIsNil) 492 device, err := s.machine.LinkLayerDevice("foo") 493 c.Assert(err, jc.ErrorIsNil) 494 495 s.removeDeviceAndAssertSuccess(c, device) 496 // Re-adding the same device should now succeed. 497 err = s.machine.SetLinkLayerDevices(args) 498 c.Assert(err, jc.ErrorIsNil) 499 } 500 501 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesNoop(c *gc.C) { 502 args := state.LinkLayerDeviceArgs{ 503 Name: "foo", 504 Type: corenetwork.EthernetDevice, 505 } 506 err := s.machine.SetLinkLayerDevices(args) 507 c.Assert(err, jc.ErrorIsNil) 508 err = s.machine.SetLinkLayerDevices(args) 509 c.Assert(err, jc.ErrorIsNil) 510 } 511 512 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesWithVirtualPort(c *gc.C) { 513 args := state.LinkLayerDeviceArgs{ 514 Name: "foo", 515 Type: corenetwork.EthernetDevice, 516 VirtualPortType: corenetwork.OvsPort, 517 } 518 err := s.machine.SetLinkLayerDevices(args) 519 c.Assert(err, jc.ErrorIsNil) 520 521 devs, err := s.machine.AllLinkLayerDevices() 522 c.Assert(err, jc.ErrorIsNil) 523 c.Assert(devs, gc.HasLen, 1) 524 c.Assert(devs[0].VirtualPortType(), gc.Equals, corenetwork.OvsPort, gc.Commentf("virtual port type field was not persisted")) 525 } 526 527 func (s *linkLayerDevicesStateSuite) removeDeviceAndAssertSuccess(c *gc.C, givenDevice *state.LinkLayerDevice) { 528 err := givenDevice.Remove() 529 c.Assert(err, jc.ErrorIsNil) 530 } 531 532 func (s *linkLayerDevicesStateSuite) TestLinkLayerDeviceRemoveTwiceStillSucceeds(c *gc.C) { 533 existingDevice := s.addSimpleDevice(c) 534 535 s.removeDeviceAndAssertSuccess(c, existingDevice) 536 s.removeDeviceAndAssertSuccess(c, existingDevice) 537 s.assertNoDevicesOnMachine(c, s.machine) 538 } 539 540 func (s *linkLayerDevicesStateSuite) TestMachineRemoveAllLinkLayerDevicesSuccess(c *gc.C) { 541 s.assertNoDevicesOnMachine(c, s.machine) 542 s.addNamedParentDeviceWithChildrenAndCheckAllAdded(c, "foo", "bar") 543 544 err := s.machine.RemoveAllLinkLayerDevices() 545 c.Assert(err, jc.ErrorIsNil) 546 s.assertNoDevicesOnMachine(c, s.machine) 547 } 548 549 func (s *linkLayerDevicesStateSuite) TestMachineRemoveAllLinkLayerDevicesNoErrorIfNoDevicesExist(c *gc.C) { 550 s.assertNoDevicesOnMachine(c, s.machine) 551 552 err := s.machine.RemoveAllLinkLayerDevices() 553 c.Assert(err, jc.ErrorIsNil) 554 } 555 556 func (s *linkLayerDevicesStateSuite) TestSetProviderIDOps(c *gc.C) { 557 dev1 := s.addNamedDevice(c, "foo") 558 559 ops, err := dev1.SetProviderIDOps("p1") 560 c.Assert(err, jc.ErrorIsNil) 561 c.Assert(ops, gc.Not(gc.HasLen), 0) 562 563 state.RunTransaction(c, s.State, ops) 564 565 dev1, err = s.machine.LinkLayerDevice("foo") 566 c.Assert(err, jc.ErrorIsNil) 567 c.Assert(dev1.ProviderID().String(), gc.Equals, "p1") 568 569 // No-op if already set. 570 ops, err = dev1.SetProviderIDOps("p1") 571 c.Assert(err, jc.ErrorIsNil) 572 c.Assert(ops, gc.HasLen, 0) 573 574 // Error if ID already used. 575 dev2 := s.addNamedDevice(c, "bar") 576 _, err = dev2.SetProviderIDOps("p1") 577 c.Assert(err, gc.ErrorMatches, "provider IDs not unique: p1") 578 579 // Unset the ID. 580 ops, err = dev1.SetProviderIDOps("") 581 c.Assert(err, jc.ErrorIsNil) 582 state.RunTransaction(c, s.State, ops) 583 584 dev1, err = s.machine.LinkLayerDevice("foo") 585 c.Assert(err, jc.ErrorIsNil) 586 c.Assert(dev1.ProviderID().String(), gc.Equals, "") 587 588 // The global ID is unregistered, so we should be able to reset it. 589 ops, err = dev1.SetProviderIDOps("p1") 590 c.Assert(err, jc.ErrorIsNil) 591 c.Assert(ops, gc.Not(gc.HasLen), 0) 592 593 // We should be able to change the ID, provided the new ID is unused. 594 ops, err = dev1.SetProviderIDOps("p2") 595 c.Assert(err, jc.ErrorIsNil) 596 c.Assert(ops, gc.Not(gc.HasLen), 0) 597 } 598 599 func (s *linkLayerDevicesStateSuite) TestRemoveOps(c *gc.C) { 600 dev := s.addNamedDevice(c, "eth0") 601 602 state.RunTransaction(c, s.State, dev.RemoveOps()) 603 604 _, err := s.State.LinkLayerDevice(dev.DocID()) 605 c.Assert(err, jc.Satisfies, errors.IsNotFound) 606 } 607 608 func (s *linkLayerDevicesStateSuite) TestUpdateOps(c *gc.C) { 609 dev := s.addNamedDevice(c, "eth0") 610 611 ops := dev.UpdateOps(state.LinkLayerDeviceArgs{ 612 Name: "eth0", 613 Type: corenetwork.EthernetDevice, 614 }) 615 c.Check(ops, gc.HasLen, 0) 616 617 mac := corenetwork.GenerateVirtualMACAddress() 618 ops = dev.UpdateOps(state.LinkLayerDeviceArgs{ 619 Name: "eth0", 620 Type: corenetwork.EthernetDevice, 621 MACAddress: mac, 622 }) 623 c.Assert(ops, gc.HasLen, 1) 624 625 state.RunTransaction(c, s.State, ops) 626 627 dev, err := s.machine.LinkLayerDevice("eth0") 628 c.Assert(err, jc.ErrorIsNil) 629 c.Check(dev.MACAddress(), gc.Equals, mac) 630 } 631 632 func (s *linkLayerDevicesStateSuite) TestEthernetDeviceForBridge(c *gc.C) { 633 _, err := s.State.AddSubnet(corenetwork.SubnetInfo{ 634 CIDR: "10.0.0.0/24", 635 ProviderId: "ps-01", 636 }) 637 c.Assert(err, jc.ErrorIsNil) 638 639 s.createBridgeWithIP(c, s.machine, "br0", "10.0.0.9/24") 640 641 dev, err := s.machine.LinkLayerDevice("br0") 642 c.Assert(err, jc.ErrorIsNil) 643 644 child, err := dev.EthernetDeviceForBridge("eth0", true) 645 c.Assert(err, jc.ErrorIsNil) 646 647 c.Check(child.InterfaceName, gc.Equals, "eth0") 648 c.Check(child.ConfigType, gc.Equals, corenetwork.ConfigStatic) 649 c.Check(child.ParentInterfaceName, gc.Equals, "br0") 650 c.Check(child.PrimaryAddress().CIDR, gc.Equals, "10.0.0.0/24") 651 c.Check(child.ProviderSubnetId, gc.Equals, corenetwork.Id("ps-01")) 652 c.Check(child.MTU, gc.Equals, int(dev.MTU())) 653 654 child, err = dev.EthernetDeviceForBridge("eth0", false) 655 c.Assert(err, jc.ErrorIsNil) 656 657 c.Check(child.ConfigType, gc.Equals, corenetwork.ConfigDHCP) 658 c.Check(child.ProviderSubnetId, gc.Equals, corenetwork.Id("")) 659 660 dev = s.addNamedDevice(c, "bond0") 661 _, err = dev.EthernetDeviceForBridge("eth0", false) 662 c.Assert(err, gc.NotNil) 663 } 664 665 func (s *linkLayerDevicesStateSuite) TestEthernetDeviceForBridgeFanMTU(c *gc.C) { 666 _, err := s.State.AddSubnet(corenetwork.SubnetInfo{ 667 CIDR: "10.0.0.0/24", 668 ProviderId: "ps-01", 669 }) 670 c.Assert(err, jc.ErrorIsNil) 671 672 _, err = s.State.AddSubnet(corenetwork.SubnetInfo{ 673 CIDR: "250.0.0.0/8", 674 FanInfo: &corenetwork.FanCIDRs{ 675 FanOverlay: "240.0.0.0/4", 676 FanLocalUnderlay: "10.0.0.0/24", 677 }, 678 }) 679 c.Assert(err, jc.ErrorIsNil) 680 681 fanBridgeName := "fan-250" 682 683 // Both of these devices are created with MTU=1450. 684 s.createNICWithIP(c, s.machine, "enp5s0", "10.0.0.6/24") 685 s.createBridgeWithIP(c, s.machine, fanBridgeName, "250.0.0.9/8") 686 687 // Create the VXLAN device used by the Fan. 688 err = s.machine.SetLinkLayerDevices( 689 state.LinkLayerDeviceArgs{ 690 Name: "ftun0", 691 Type: corenetwork.VXLANDevice, 692 ParentName: fanBridgeName, 693 IsUp: true, 694 MTU: 1400, 695 }, 696 ) 697 c.Assert(err, jc.ErrorIsNil) 698 699 dev, err := s.machine.LinkLayerDevice("fan-250") 700 c.Assert(err, jc.ErrorIsNil) 701 702 child, err := dev.EthernetDeviceForBridge("eth0", true) 703 c.Assert(err, jc.ErrorIsNil) 704 705 // A child device of the fan should get an MTU equal to the VXLAN. 706 c.Assert(child.MTU, gc.Equals, 1400) 707 } 708 709 func (s *linkLayerDevicesStateSuite) TestAddAddressOps(c *gc.C) { 710 dev := s.addNamedDevice(c, "eth0") 711 712 ops, err := dev.AddAddressOps(state.LinkLayerDeviceAddress{ 713 DeviceName: "", // Not required. 714 CIDRAddress: "10.1.1.1/24", 715 Origin: corenetwork.OriginMachine, 716 IsSecondary: true, 717 }) 718 c.Assert(err, jc.ErrorIsNil) 719 720 state.RunTransaction(c, s.State, ops) 721 722 dev, err = s.machine.LinkLayerDevice("eth0") 723 c.Assert(err, jc.ErrorIsNil) 724 725 addrs, err := dev.Addresses() 726 c.Assert(err, jc.ErrorIsNil) 727 728 c.Assert(addrs, gc.HasLen, 1) 729 c.Check(addrs[0].Value(), gc.Equals, "10.1.1.1") 730 c.Check(addrs[0].IsSecondary(), gc.Equals, true) 731 } 732 733 func (s *linkLayerDevicesStateSuite) TestAddDeviceOpsWithAddresses(c *gc.C) { 734 devName := "eth0" 735 736 devArgs := state.LinkLayerDeviceArgs{ 737 Name: devName, 738 Type: corenetwork.EthernetDevice, 739 } 740 741 addrArgs := state.LinkLayerDeviceAddress{ 742 DeviceName: devName, 743 CIDRAddress: "10.1.1.1/24", 744 Origin: corenetwork.OriginMachine, 745 } 746 747 ops, err := s.machine.AddLinkLayerDeviceOps(devArgs, addrArgs) 748 c.Assert(err, jc.ErrorIsNil) 749 750 state.RunTransaction(c, s.State, ops) 751 752 _, err = s.machine.LinkLayerDevice(devName) 753 c.Assert(err, jc.ErrorIsNil) 754 755 dev, err := s.machine.LinkLayerDevice("eth0") 756 c.Assert(err, jc.ErrorIsNil) 757 758 addrs, err := dev.Addresses() 759 c.Assert(err, jc.ErrorIsNil) 760 761 c.Assert(addrs, gc.HasLen, 1) 762 c.Assert(addrs[0].Value(), gc.Equals, "10.1.1.1") 763 } 764 765 func (s *linkLayerDevicesStateSuite) createSpaceAndSubnetWithProviderID(c *gc.C, spaceName, CIDR, providerSubnetID string) { 766 space, err := s.State.AddSpace(spaceName, corenetwork.Id(spaceName), nil, true) 767 c.Assert(err, jc.ErrorIsNil) 768 spaceInfo, err := space.NetworkSpace() 769 c.Assert(err, gc.IsNil) 770 s.spaces[spaceName] = spaceInfo 771 772 _, err = s.State.AddSubnet(corenetwork.SubnetInfo{ 773 CIDR: CIDR, 774 SpaceID: space.Id(), 775 ProviderId: corenetwork.Id(providerSubnetID), 776 }) 777 c.Assert(err, jc.ErrorIsNil) 778 } 779 780 func (s *linkLayerDevicesStateSuite) createNICWithIP(c *gc.C, machine *state.Machine, deviceName, cidrAddress string) { 781 err := machine.SetLinkLayerDevices( 782 state.LinkLayerDeviceArgs{ 783 Name: deviceName, 784 Type: corenetwork.EthernetDevice, 785 ParentName: "", 786 IsUp: true, 787 MTU: 1450, 788 }, 789 ) 790 c.Assert(err, jc.ErrorIsNil) 791 err = machine.SetDevicesAddresses( 792 state.LinkLayerDeviceAddress{ 793 DeviceName: deviceName, 794 CIDRAddress: cidrAddress, 795 ConfigMethod: corenetwork.ConfigStatic, 796 }, 797 ) 798 c.Assert(err, jc.ErrorIsNil) 799 } 800 801 func (s *linkLayerDevicesStateSuite) createBridgeWithIP(c *gc.C, machine *state.Machine, bridgeName, cidrAddress string) { 802 err := machine.SetLinkLayerDevices( 803 state.LinkLayerDeviceArgs{ 804 Name: bridgeName, 805 Type: corenetwork.BridgeDevice, 806 ParentName: "", 807 IsUp: true, 808 MTU: 1450, 809 }, 810 ) 811 c.Assert(err, jc.ErrorIsNil) 812 err = machine.SetDevicesAddresses( 813 state.LinkLayerDeviceAddress{ 814 DeviceName: bridgeName, 815 CIDRAddress: cidrAddress, 816 ConfigMethod: corenetwork.ConfigStatic, 817 }, 818 ) 819 c.Assert(err, jc.ErrorIsNil) 820 } 821 822 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesWithLightStateChurn(c *gc.C) { 823 childArgs, churnHook := s.prepareSetLinkLayerDevicesWithStateChurn(c) 824 defer state.SetTestHooks(c, s.State, churnHook).Check() 825 s.assertAllLinkLayerDevicesOnMachineMatchCount(c, s.machine, 1) // parent only 826 827 err := s.machine.SetLinkLayerDevices(childArgs) 828 c.Assert(err, jc.ErrorIsNil) 829 s.assertAllLinkLayerDevicesOnMachineMatchCount(c, s.machine, 2) // both parent and child remain 830 } 831 832 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesUpdatesExistingDocs(c *gc.C) { 833 s.assertNoDevicesOnMachine(c, s.machine) 834 parent, children := s.addNamedParentDeviceWithChildrenAndCheckAllAdded(c, "foo", "bar") 835 836 // Change everything that's possible to change for both existing devices, 837 // except for ProviderID and ParentName (tested separately). 838 updateArgs := []state.LinkLayerDeviceArgs{{ 839 Name: parent.Name(), 840 Type: corenetwork.BondDevice, 841 MTU: 1234, 842 MACAddress: "aa:bb:cc:dd:ee:f0", 843 IsAutoStart: true, 844 IsUp: true, 845 }, { 846 Name: children[0].Name(), 847 Type: corenetwork.VLAN8021QDevice, 848 MTU: 4321, 849 MACAddress: "aa:bb:cc:dd:ee:f1", 850 IsAutoStart: true, 851 IsUp: true, 852 ParentName: parent.Name(), 853 }} 854 err := s.machine.SetLinkLayerDevices(updateArgs...) 855 c.Assert(err, jc.ErrorIsNil) 856 857 allDevices, err := s.machine.AllLinkLayerDevices() 858 c.Assert(err, jc.ErrorIsNil) 859 c.Assert(allDevices, gc.HasLen, 2) 860 861 for _, device := range allDevices { 862 if device.Name() == parent.Name() { 863 s.checkSetDeviceMatchesArgs(c, device, updateArgs[0]) 864 } else { 865 s.checkSetDeviceMatchesArgs(c, device, updateArgs[1]) 866 } 867 s.checkSetDeviceMatchesMachineIDAndModelUUID(c, device, s.machine.Id(), s.State.ModelUUID()) 868 } 869 } 870 871 func (s *linkLayerDevicesStateSuite) prepareSetLinkLayerDevicesWithStateChurn(c *gc.C) (state.LinkLayerDeviceArgs, jujutxn.TestHook) { 872 parent := s.addNamedDevice(c, "parent") 873 childArgs := state.LinkLayerDeviceArgs{ 874 Name: "child", 875 Type: corenetwork.EthernetDevice, 876 ParentName: parent.Name(), 877 } 878 879 churnHook := jujutxn.TestHook{ 880 Before: func() { 881 s.assertAllLinkLayerDevicesOnMachineMatchCount(c, s.machine, 1) // just the parent 882 err := s.machine.SetLinkLayerDevices(childArgs) 883 c.Assert(err, jc.ErrorIsNil) 884 }, 885 After: func() { 886 s.assertAllLinkLayerDevicesOnMachineMatchCount(c, s.machine, 2) // parent and child 887 child, err := s.machine.LinkLayerDevice("child") 888 c.Assert(err, jc.ErrorIsNil) 889 err = child.Remove() 890 c.Assert(err, jc.ErrorIsNil) 891 }, 892 } 893 894 return childArgs, churnHook 895 } 896 897 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesWithModerateStateChurn(c *gc.C) { 898 childArgs, churnHook := s.prepareSetLinkLayerDevicesWithStateChurn(c) 899 defer state.SetTestHooks(c, s.State, churnHook, churnHook).Check() 900 s.assertAllLinkLayerDevicesOnMachineMatchCount(c, s.machine, 1) // parent only 901 902 err := s.machine.SetLinkLayerDevices(childArgs) 903 c.Assert(err, jc.ErrorIsNil) 904 s.assertAllLinkLayerDevicesOnMachineMatchCount(c, s.machine, 2) // both parent and child remain 905 } 906 907 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesWithTooMuchStateChurn(c *gc.C) { 908 childArgs, churnHook := s.prepareSetLinkLayerDevicesWithStateChurn(c) 909 state.SetMaxTxnAttempts(c, s.State, 3) 910 defer state.SetTestHooks(c, s.State, churnHook, churnHook, churnHook).Check() 911 s.assertAllLinkLayerDevicesOnMachineMatchCount(c, s.machine, 1) // parent only 912 913 err := s.machine.SetLinkLayerDevices(childArgs) 914 c.Assert(errors.Cause(err), gc.Equals, jujutxn.ErrExcessiveContention) 915 s.assertAllLinkLayerDevicesOnMachineMatchCount(c, s.machine, 1) // only the parent remains 916 } 917 918 func (s *linkLayerDevicesStateSuite) addContainerMachine(c *gc.C) { 919 // Add a container machine with s.machine as its host. 920 containerTemplate := state.MachineTemplate{ 921 Base: state.UbuntuBase("12.10"), 922 Jobs: []state.MachineJob{state.JobHostUnits}, 923 } 924 container, err := s.State.AddMachineInsideMachine(containerTemplate, s.machine.Id(), instance.LXD) 925 c.Assert(err, jc.ErrorIsNil) 926 s.containerMachine = container 927 } 928 929 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesAllowsParentBridgeDeviceForContainerDevice(c *gc.C) { 930 // Add default bridges per container type to ensure they will be skipped 931 // when deciding which host bridges to use for the container NICs. 932 s.addParentBridgeDeviceWithContainerDevicesAsChildren(c, network.DefaultLXDBridge, "vethX", 1) 933 s.addParentBridgeDeviceWithContainerDevicesAsChildren(c, network.DefaultKVMBridge, "vethY", 1) 934 parentDevice, _ := s.addParentBridgeDeviceWithContainerDevicesAsChildren(c, "br-eth1.250", "eth", 1) 935 childDevice, err := s.containerMachine.LinkLayerDevice("eth0") 936 c.Assert(err, jc.ErrorIsNil) 937 938 c.Check(childDevice.Name(), gc.Equals, "eth0") 939 c.Check(childDevice.ParentName(), gc.Equals, "m#0#d#br-eth1.250") 940 c.Check(childDevice.MachineID(), gc.Equals, s.containerMachine.Id()) 941 parentOfChildDevice, err := childDevice.ParentDevice() 942 c.Assert(err, jc.ErrorIsNil) 943 c.Check(parentOfChildDevice, jc.DeepEquals, parentDevice) 944 } 945 946 func (s *linkLayerDevicesStateSuite) addParentBridgeDeviceWithContainerDevicesAsChildren( 947 c *gc.C, 948 parentName string, 949 childDevicesNamePrefix string, 950 numChildren int, 951 ) (parentDevice *state.LinkLayerDevice, childrenDevices []*state.LinkLayerDevice) { 952 parentArgs := state.LinkLayerDeviceArgs{ 953 Name: parentName, 954 Type: corenetwork.BridgeDevice, 955 } 956 parentDevice = s.assertSetLinkLayerDevicesSucceedsAndResultMatchesArgs(c, parentArgs) 957 parentDeviceGlobalKey := "m#" + s.machine.Id() + "#d#" + parentName 958 959 childrenArgsTemplate := state.LinkLayerDeviceArgs{ 960 Type: corenetwork.EthernetDevice, 961 ParentName: parentDeviceGlobalKey, 962 } 963 childrenArgs := make([]state.LinkLayerDeviceArgs, numChildren) 964 for i := 0; i < numChildren; i++ { 965 childrenArgs[i] = childrenArgsTemplate 966 childrenArgs[i].Name = fmt.Sprintf("%s%d", childDevicesNamePrefix, i) 967 } 968 s.addContainerMachine(c) 969 err := s.containerMachine.SetLinkLayerDevices(childrenArgs...) 970 c.Assert(err, jc.ErrorIsNil) 971 childrenDevices, err = s.containerMachine.AllLinkLayerDevices() 972 c.Assert(err, jc.ErrorIsNil) 973 return parentDevice, childrenDevices 974 } 975 976 func (s *linkLayerDevicesStateSuite) TestLinkLayerDeviceRemoveFailsWithExistingChildrenOnContainerMachine(c *gc.C) { 977 parent, children := s.addParentBridgeDeviceWithContainerDevicesAsChildren(c, "br-eth1", "eth", 2) 978 979 err := parent.Remove() 980 expectedErrorPrefix := fmt.Sprintf("cannot remove %s: parent device %q has ", parent, parent.Name()) 981 c.Assert(err, gc.ErrorMatches, expectedErrorPrefix+"2 children") 982 c.Assert(err, jc.Satisfies, state.IsParentDeviceHasChildrenError) 983 984 err = children[0].Remove() 985 c.Assert(err, jc.ErrorIsNil) 986 987 err = parent.Remove() 988 c.Assert(err, gc.ErrorMatches, expectedErrorPrefix+"1 children") 989 c.Assert(err, jc.Satisfies, state.IsParentDeviceHasChildrenError) 990 991 err = children[1].Remove() 992 c.Assert(err, jc.ErrorIsNil) 993 err = parent.Remove() 994 c.Assert(err, jc.ErrorIsNil) 995 } 996 997 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesUpdatesBothExistingAndNewParents(c *gc.C) { 998 parent1, children1 := s.addNamedParentDeviceWithChildrenAndCheckAllAdded(c, "parent1", "child1", "child2") 999 parent2, children2 := s.addNamedParentDeviceWithChildrenAndCheckAllAdded(c, "parent2", "child3", "child4") 1000 1001 // Swap the parents of all children. 1002 updateArgs := make([]state.LinkLayerDeviceArgs, 0, len(children1)+len(children2)) 1003 for _, child := range children1 { 1004 updateArgs = append(updateArgs, state.LinkLayerDeviceArgs{ 1005 Name: child.Name(), 1006 Type: child.Type(), 1007 ParentName: parent2.Name(), 1008 }) 1009 } 1010 for _, child := range children2 { 1011 updateArgs = append(updateArgs, state.LinkLayerDeviceArgs{ 1012 Name: child.Name(), 1013 Type: child.Type(), 1014 ParentName: parent1.Name(), 1015 }) 1016 } 1017 err := s.machine.SetLinkLayerDevices(updateArgs...) 1018 c.Assert(err, jc.ErrorIsNil) 1019 1020 allDevices, err := s.machine.AllLinkLayerDevices() 1021 c.Assert(err, jc.ErrorIsNil) 1022 c.Assert(allDevices, gc.HasLen, len(updateArgs)+2) // 4 children updated and 2 parents unchanged. 1023 1024 for _, device := range allDevices { 1025 switch device.Name() { 1026 case children1[0].Name(), children1[1].Name(): 1027 c.Check(device.ParentName(), gc.Equals, parent2.Name()) 1028 case children2[0].Name(), children2[1].Name(): 1029 c.Check(device.ParentName(), gc.Equals, parent1.Name()) 1030 } 1031 } 1032 } 1033 1034 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesUpdatesParentWhenNotSet(c *gc.C) { 1035 parent := s.addNamedDevice(c, "parent") 1036 child := s.addNamedDevice(c, "child") 1037 1038 updateArgs := state.LinkLayerDeviceArgs{ 1039 Name: child.Name(), 1040 Type: child.Type(), 1041 ParentName: parent.Name(), // make "child" a child of "parent" 1042 } 1043 err := s.machine.SetLinkLayerDevices(updateArgs) 1044 c.Assert(err, jc.ErrorIsNil) 1045 1046 err = parent.Remove() 1047 c.Assert(err, gc.ErrorMatches, 1048 `cannot remove ethernet device "parent" on machine "0": parent device "parent" has 1 children`, 1049 ) 1050 c.Assert(err, jc.Satisfies, state.IsParentDeviceHasChildrenError) 1051 } 1052 1053 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesUpdatesParentWhenSet(c *gc.C) { 1054 parent, children := s.addNamedParentDeviceWithChildrenAndCheckAllAdded(c, "parent", "child") 1055 err := parent.Remove() 1056 c.Assert(err, jc.Satisfies, state.IsParentDeviceHasChildrenError) 1057 1058 updateArgs := state.LinkLayerDeviceArgs{ 1059 Name: children[0].Name(), 1060 Type: children[0].Type(), 1061 // make "child" no longer a child of "parent" 1062 } 1063 err = s.machine.SetLinkLayerDevices(updateArgs) 1064 c.Assert(err, jc.ErrorIsNil) 1065 1066 err = parent.Remove() 1067 c.Assert(err, jc.ErrorIsNil) 1068 } 1069 1070 func (s *linkLayerDevicesStateSuite) TestSetLinkLayerDevicesToContainerWhenContainerDeadBeforehand(c *gc.C) { 1071 beforeHook := func() { 1072 // Make the container Dead but keep it around. 1073 err := s.containerMachine.EnsureDead() 1074 c.Assert(err, jc.ErrorIsNil) 1075 } 1076 1077 s.assertSetLinkLayerDevicesToContainerFailsWithBeforeHook(c, beforeHook, `.*machine "0/lxd/0" not alive`) 1078 } 1079 1080 func (s *linkLayerDevicesStateSuite) assertSetLinkLayerDevicesToContainerFailsWithBeforeHook(c *gc.C, beforeHook func(), expectedError string) { 1081 _, children := s.addParentBridgeDeviceWithContainerDevicesAsChildren(c, "br-eth1", "eth", 1) 1082 defer state.SetBeforeHooks(c, s.State, beforeHook).Check() 1083 1084 newChildArgs := state.LinkLayerDeviceArgs{ 1085 Name: "eth1", 1086 Type: corenetwork.EthernetDevice, 1087 ParentName: children[0].ParentName(), 1088 } 1089 err := s.containerMachine.SetLinkLayerDevices(newChildArgs) 1090 c.Assert(err, gc.ErrorMatches, expectedError) 1091 } 1092 1093 func (s *linkLayerDevicesStateSuite) TestMachineRemoveAlsoRemoveAllLinkLayerDevices(c *gc.C) { 1094 s.assertNoDevicesOnMachine(c, s.machine) 1095 s.addNamedParentDeviceWithChildrenAndCheckAllAdded(c, "foo", "bar") 1096 1097 err := s.machine.EnsureDead() 1098 c.Assert(err, jc.ErrorIsNil) 1099 err = s.machine.Remove() 1100 c.Assert(err, jc.ErrorIsNil) 1101 1102 s.assertNoDevicesOnMachine(c, s.machine) 1103 } 1104 1105 func (s *linkLayerDevicesStateSuite) TestSetDeviceAddressesWithSubnetID(c *gc.C) { 1106 s.createSpaceAndSubnetWithProviderID(c, "public", "10.0.0.0/24", "prov-0000") 1107 s.createSpaceAndSubnetWithProviderID(c, "private", "10.20.0.0/24", "prov-ffff") 1108 s.createSpaceAndSubnetWithProviderID(c, "dmz", "10.30.0.0/24", "prov-abcd") 1109 s.createNICWithIP(c, s.machine, "eth0", "10.0.0.11/24") 1110 s.createNICWithIP(c, s.machine, "eth1", "10.20.0.42/24") 1111 // Create eth2 NIC but don't assign an IP yet. This allows us to 1112 // exercise the both the insert and update code-paths when calling 1113 // SetDevicesAddresses. 1114 err := s.machine.SetLinkLayerDevices( 1115 state.LinkLayerDeviceArgs{ 1116 Name: "eth2", 1117 Type: corenetwork.EthernetDevice, 1118 ParentName: "", 1119 IsUp: true, 1120 }, 1121 ) 1122 c.Assert(err, jc.ErrorIsNil) 1123 1124 err = s.machine.SetDevicesAddresses( 1125 state.LinkLayerDeviceAddress{ 1126 DeviceName: "eth1", 1127 ConfigMethod: corenetwork.ConfigStatic, 1128 ProviderNetworkID: "vpc-abcd", 1129 ProviderSubnetID: "prov-ffff", 1130 CIDRAddress: "10.20.0.42/24", 1131 }, 1132 state.LinkLayerDeviceAddress{ 1133 DeviceName: "eth2", 1134 ConfigMethod: corenetwork.ConfigStatic, 1135 ProviderNetworkID: "vpc-abcd", 1136 ProviderSubnetID: "prov-abcd", 1137 CIDRAddress: "10.30.0.99/24", 1138 }, 1139 ) 1140 c.Assert(err, jc.ErrorIsNil) 1141 1142 allAddr, err := s.machine.AllDeviceAddresses() 1143 c.Assert(err, gc.IsNil) 1144 1145 expSubnetID := map[string]corenetwork.Id{ 1146 "eth1": "prov-ffff", 1147 "eth2": "prov-abcd", 1148 } 1149 nextDev: 1150 for devName, expID := range expSubnetID { 1151 for _, addr := range allAddr { 1152 if addr.DeviceName() != devName { 1153 continue 1154 } 1155 1156 c.Assert(addr.ProviderSubnetID(), gc.Equals, expID, gc.Commentf("subnetID for device %q", devName)) 1157 continue nextDev 1158 } 1159 c.Fatalf("unable to locate device %q while enumerating machine addresses", devName) 1160 } 1161 }