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