github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/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  }