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