github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/state/linklayerdevices_test.go (about)

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