github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/worker/provisioner/container_initialisation_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package provisioner_test
     5  
     6  import (
     7  	"fmt"
     8  	"io/ioutil"
     9  	"os"
    10  	"os/exec"
    11  	"path/filepath"
    12  	"runtime"
    13  
    14  	"github.com/juju/names"
    15  	"github.com/juju/testing"
    16  	jc "github.com/juju/testing/checkers"
    17  	"github.com/juju/utils/featureflag"
    18  	"github.com/juju/utils/fslock"
    19  	"github.com/juju/utils/packaging/manager"
    20  	gc "gopkg.in/check.v1"
    21  
    22  	"github.com/juju/juju/agent"
    23  	apiprovisioner "github.com/juju/juju/api/provisioner"
    24  	"github.com/juju/juju/container"
    25  	containertesting "github.com/juju/juju/container/testing"
    26  	"github.com/juju/juju/environs"
    27  	"github.com/juju/juju/feature"
    28  	"github.com/juju/juju/instance"
    29  	"github.com/juju/juju/juju/arch"
    30  	"github.com/juju/juju/juju/osenv"
    31  	"github.com/juju/juju/provider/dummy"
    32  	"github.com/juju/juju/state"
    33  	coretesting "github.com/juju/juju/testing"
    34  	"github.com/juju/juju/tools"
    35  	"github.com/juju/juju/version"
    36  	"github.com/juju/juju/worker"
    37  	"github.com/juju/juju/worker/provisioner"
    38  )
    39  
    40  type ContainerSetupSuite struct {
    41  	CommonProvisionerSuite
    42  	p           provisioner.Provisioner
    43  	agentConfig agent.ConfigSetter
    44  	// Record the apt commands issued as part of container initialisation
    45  	aptCmdChan  <-chan *exec.Cmd
    46  	initLockDir string
    47  	initLock    *fslock.Lock
    48  	fakeLXCNet  string
    49  }
    50  
    51  var _ = gc.Suite(&ContainerSetupSuite{})
    52  
    53  func (s *ContainerSetupSuite) SetUpSuite(c *gc.C) {
    54  	// TODO(bogdanteleaga): Fix this on windows
    55  	if runtime.GOOS == "windows" {
    56  		c.Skip("bug 1403084: Skipping container tests on windows")
    57  	}
    58  	s.CommonProvisionerSuite.SetUpSuite(c)
    59  }
    60  
    61  func (s *ContainerSetupSuite) TearDownSuite(c *gc.C) {
    62  	s.CommonProvisionerSuite.TearDownSuite(c)
    63  }
    64  
    65  func allFatal(error) bool {
    66  	return true
    67  }
    68  
    69  func noImportance(err0, err1 error) bool {
    70  	return false
    71  }
    72  
    73  func (s *ContainerSetupSuite) SetUpTest(c *gc.C) {
    74  	s.CommonProvisionerSuite.SetUpTest(c)
    75  	aptCmdChan := s.HookCommandOutput(&manager.CommandOutput, []byte{}, nil)
    76  	s.aptCmdChan = aptCmdChan
    77  
    78  	// Set up provisioner for the state machine.
    79  	s.agentConfig = s.AgentConfigForTag(c, names.NewMachineTag("0"))
    80  	s.p = provisioner.NewEnvironProvisioner(s.provisioner, s.agentConfig)
    81  
    82  	// Create a new container initialisation lock.
    83  	s.initLockDir = c.MkDir()
    84  	initLock, err := fslock.NewLock(s.initLockDir, "container-init")
    85  	c.Assert(err, jc.ErrorIsNil)
    86  	s.initLock = initLock
    87  
    88  	// Patch to isolate the test from the host machine.
    89  	s.fakeLXCNet = filepath.Join(c.MkDir(), "lxc-net")
    90  	s.PatchValue(provisioner.EtcDefaultLXCNetPath, s.fakeLXCNet)
    91  }
    92  
    93  func (s *ContainerSetupSuite) TearDownTest(c *gc.C) {
    94  	stop(c, s.p)
    95  	s.CommonProvisionerSuite.TearDownTest(c)
    96  }
    97  
    98  func (s *ContainerSetupSuite) setupContainerWorker(c *gc.C, tag names.MachineTag) (worker.StringsWatchHandler, worker.Runner) {
    99  	testing.PatchExecutable(c, s, "ubuntu-cloudimg-query", containertesting.FakeLxcURLScript)
   100  	runner := worker.NewRunner(allFatal, noImportance)
   101  	pr := s.st.Provisioner()
   102  	machine, err := pr.Machine(tag)
   103  	c.Assert(err, jc.ErrorIsNil)
   104  	err = machine.SetSupportedContainers(instance.ContainerTypes...)
   105  	c.Assert(err, jc.ErrorIsNil)
   106  	cfg := s.AgentConfigForTag(c, tag)
   107  
   108  	watcherName := fmt.Sprintf("%s-container-watcher", machine.Id())
   109  	params := provisioner.ContainerSetupParams{
   110  		Runner:              runner,
   111  		WorkerName:          watcherName,
   112  		SupportedContainers: instance.ContainerTypes,
   113  		ImageURLGetter:      &containertesting.MockURLGetter{},
   114  		Machine:             machine,
   115  		Provisioner:         pr,
   116  		Config:              cfg,
   117  		InitLock:            s.initLock,
   118  	}
   119  	handler := provisioner.NewContainerSetupHandler(params)
   120  	runner.StartWorker(watcherName, func() (worker.Worker, error) {
   121  		return worker.NewStringsWorker(handler), nil
   122  	})
   123  	return handler, runner
   124  }
   125  
   126  func (s *ContainerSetupSuite) createContainer(c *gc.C, host *state.Machine, ctype instance.ContainerType) {
   127  	inst := s.checkStartInstanceNoSecureConnection(c, host)
   128  	s.setupContainerWorker(c, host.Tag().(names.MachineTag))
   129  
   130  	// make a container on the host machine
   131  	template := state.MachineTemplate{
   132  		Series: coretesting.FakeDefaultSeries,
   133  		Jobs:   []state.MachineJob{state.JobHostUnits},
   134  	}
   135  	container, err := s.State.AddMachineInsideMachine(template, host.Id(), ctype)
   136  	c.Assert(err, jc.ErrorIsNil)
   137  
   138  	// the host machine agent should not attempt to create the container
   139  	s.checkNoOperations(c)
   140  
   141  	// cleanup
   142  	c.Assert(container.EnsureDead(), gc.IsNil)
   143  	c.Assert(container.Remove(), gc.IsNil)
   144  	c.Assert(host.EnsureDead(), gc.IsNil)
   145  	s.checkStopInstances(c, inst)
   146  	s.waitRemoved(c, host)
   147  }
   148  
   149  func (s *ContainerSetupSuite) assertContainerProvisionerStarted(
   150  	c *gc.C, host *state.Machine, ctype instance.ContainerType) {
   151  
   152  	// A stub worker callback to record what happens.
   153  	provisionerStarted := false
   154  	startProvisionerWorker := func(runner worker.Runner, containerType instance.ContainerType,
   155  		pr *apiprovisioner.State, cfg agent.Config, broker environs.InstanceBroker,
   156  		toolsFinder provisioner.ToolsFinder) error {
   157  		c.Assert(containerType, gc.Equals, ctype)
   158  		c.Assert(cfg.Tag(), gc.Equals, host.Tag())
   159  		provisionerStarted = true
   160  		return nil
   161  	}
   162  	s.PatchValue(&provisioner.StartProvisioner, startProvisionerWorker)
   163  
   164  	s.createContainer(c, host, ctype)
   165  	// Consume the apt command used to initialise the container.
   166  	<-s.aptCmdChan
   167  
   168  	// the container worker should have created the provisioner
   169  	c.Assert(provisionerStarted, jc.IsTrue)
   170  }
   171  
   172  func (s *ContainerSetupSuite) TestContainerProvisionerStarted(c *gc.C) {
   173  	for _, ctype := range instance.ContainerTypes {
   174  		// create a machine to host the container.
   175  		m, err := s.BackingState.AddOneMachine(state.MachineTemplate{
   176  			Series:      coretesting.FakeDefaultSeries,
   177  			Jobs:        []state.MachineJob{state.JobHostUnits},
   178  			Constraints: s.defaultConstraints,
   179  		})
   180  		c.Assert(err, jc.ErrorIsNil)
   181  		err = m.SetSupportedContainers([]instance.ContainerType{instance.LXC, instance.KVM})
   182  		c.Assert(err, jc.ErrorIsNil)
   183  		err = m.SetAgentVersion(version.Current)
   184  		c.Assert(err, jc.ErrorIsNil)
   185  		s.assertContainerProvisionerStarted(c, m, ctype)
   186  	}
   187  }
   188  
   189  func (s *ContainerSetupSuite) TestLxcContainerUsesConstraintsArch(c *gc.C) {
   190  	// LXC should override the architecture in constraints with the
   191  	// host's architecture.
   192  	s.PatchValue(&version.Current.Arch, arch.PPC64EL)
   193  	s.testContainerConstraintsArch(c, instance.LXC, arch.PPC64EL)
   194  }
   195  
   196  func (s *ContainerSetupSuite) TestKvmContainerUsesHostArch(c *gc.C) {
   197  	// KVM should do what it's told, and use the architecture in
   198  	// constraints.
   199  	s.PatchValue(&version.Current.Arch, arch.PPC64EL)
   200  	s.testContainerConstraintsArch(c, instance.KVM, arch.AMD64)
   201  }
   202  
   203  func (s *ContainerSetupSuite) testContainerConstraintsArch(c *gc.C, containerType instance.ContainerType, expectArch string) {
   204  	var called bool
   205  	s.PatchValue(provisioner.GetToolsFinder, func(*apiprovisioner.State) provisioner.ToolsFinder {
   206  		return toolsFinderFunc(func(v version.Number, series string, arch *string) (tools.List, error) {
   207  			called = true
   208  			c.Assert(arch, gc.NotNil)
   209  			c.Assert(*arch, gc.Equals, expectArch)
   210  			result := version.Current
   211  			result.Number = v
   212  			result.Series = series
   213  			result.Arch = *arch
   214  			return tools.List{{Version: result}}, nil
   215  		})
   216  	})
   217  
   218  	s.PatchValue(&provisioner.StartProvisioner, func(runner worker.Runner, containerType instance.ContainerType,
   219  		pr *apiprovisioner.State, cfg agent.Config, broker environs.InstanceBroker,
   220  		toolsFinder provisioner.ToolsFinder) error {
   221  		amd64 := arch.AMD64
   222  		toolsFinder.FindTools(version.Current.Number, version.Current.Series, &amd64)
   223  		return nil
   224  	})
   225  
   226  	// create a machine to host the container.
   227  	m, err := s.BackingState.AddOneMachine(state.MachineTemplate{
   228  		Series:      coretesting.FakeDefaultSeries,
   229  		Jobs:        []state.MachineJob{state.JobHostUnits},
   230  		Constraints: s.defaultConstraints,
   231  	})
   232  	c.Assert(err, jc.ErrorIsNil)
   233  	err = m.SetSupportedContainers([]instance.ContainerType{containerType})
   234  	c.Assert(err, jc.ErrorIsNil)
   235  	err = m.SetAgentVersion(version.Current)
   236  	c.Assert(err, jc.ErrorIsNil)
   237  
   238  	s.createContainer(c, m, containerType)
   239  	<-s.aptCmdChan
   240  	c.Assert(called, jc.IsTrue)
   241  }
   242  
   243  func (s *ContainerSetupSuite) TestLxcContainerUsesImageURL(c *gc.C) {
   244  	// create a machine to host the container.
   245  	m, err := s.BackingState.AddOneMachine(state.MachineTemplate{
   246  		Series:      coretesting.FakeDefaultSeries,
   247  		Jobs:        []state.MachineJob{state.JobHostUnits},
   248  		Constraints: s.defaultConstraints,
   249  	})
   250  	c.Assert(err, jc.ErrorIsNil)
   251  	err = m.SetSupportedContainers([]instance.ContainerType{instance.LXC, instance.KVM})
   252  	c.Assert(err, jc.ErrorIsNil)
   253  	err = m.SetAgentVersion(version.Current)
   254  	c.Assert(err, jc.ErrorIsNil)
   255  
   256  	brokerCalled := false
   257  	newlxcbroker := func(api provisioner.APICalls, agentConfig agent.Config, managerConfig container.ManagerConfig,
   258  		imageURLGetter container.ImageURLGetter, enableNAT bool, defaultMTU int) (environs.InstanceBroker, error) {
   259  		imageURL, err := imageURLGetter.ImageURL(instance.LXC, "trusty", "amd64")
   260  		c.Assert(err, jc.ErrorIsNil)
   261  		c.Assert(imageURL, gc.Equals, "imageURL")
   262  		c.Assert(imageURLGetter.CACert(), gc.DeepEquals, []byte("cert"))
   263  		brokerCalled = true
   264  		return nil, fmt.Errorf("lxc broker error")
   265  	}
   266  	s.PatchValue(&provisioner.NewLxcBroker, newlxcbroker)
   267  	s.createContainer(c, m, instance.LXC)
   268  	c.Assert(brokerCalled, jc.IsTrue)
   269  }
   270  
   271  func (s *ContainerSetupSuite) TestContainerManagerConfigName(c *gc.C) {
   272  	pr := s.st.Provisioner()
   273  	expect := func(expect string) {
   274  		cfg, err := provisioner.ContainerManagerConfig(instance.KVM, pr, s.agentConfig)
   275  		c.Assert(err, jc.ErrorIsNil)
   276  		c.Assert(cfg[container.ConfigName], gc.Equals, expect)
   277  	}
   278  	expect("juju")
   279  	s.agentConfig.SetValue(agent.Namespace, "any-old-thing")
   280  	expect("any-old-thing")
   281  }
   282  
   283  func (s *ContainerSetupSuite) assertContainerInitialised(c *gc.C, ctype instance.ContainerType, packages [][]string, addressable bool) {
   284  	// A noop worker callback.
   285  	startProvisionerWorker := func(runner worker.Runner, containerType instance.ContainerType,
   286  		pr *apiprovisioner.State, cfg agent.Config, broker environs.InstanceBroker,
   287  		toolsFinder provisioner.ToolsFinder) error {
   288  		return nil
   289  	}
   290  	s.PatchValue(&provisioner.StartProvisioner, startProvisionerWorker)
   291  
   292  	// create a machine to host the container.
   293  	m, err := s.BackingState.AddOneMachine(state.MachineTemplate{
   294  		Series:      "precise", // precise requires special apt parameters, so we use that series here.
   295  		Jobs:        []state.MachineJob{state.JobHostUnits},
   296  		Constraints: s.defaultConstraints,
   297  	})
   298  	c.Assert(err, jc.ErrorIsNil)
   299  	err = m.SetSupportedContainers([]instance.ContainerType{instance.LXC, instance.KVM})
   300  	c.Assert(err, jc.ErrorIsNil)
   301  	err = m.SetAgentVersion(version.Current)
   302  	c.Assert(err, jc.ErrorIsNil)
   303  
   304  	// Before starting /etc/default/lxc-net should be missing.
   305  	c.Assert(s.fakeLXCNet, jc.DoesNotExist)
   306  
   307  	s.createContainer(c, m, ctype)
   308  
   309  	// Only feature-flagged addressable containers modify lxc-net.
   310  	if addressable {
   311  		// After initialisation starts, but before running the
   312  		// initializer, lxc-net should be created if ctype is LXC, as the
   313  		// dummy provider supports static address allocation by default.
   314  		if ctype == instance.LXC {
   315  			AssertFileContains(c, s.fakeLXCNet, provisioner.EtcDefaultLXCNet)
   316  			defer os.Remove(s.fakeLXCNet)
   317  		} else {
   318  			c.Assert(s.fakeLXCNet, jc.DoesNotExist)
   319  		}
   320  	}
   321  
   322  	for _, pack := range packages {
   323  		cmd := <-s.aptCmdChan
   324  		expected := []string{
   325  			"apt-get", "--option=Dpkg::Options::=--force-confold",
   326  			"--option=Dpkg::options::=--force-unsafe-io", "--assume-yes", "--quiet",
   327  			"install"}
   328  		expected = append(expected, pack...)
   329  		c.Assert(cmd.Args, gc.DeepEquals, expected)
   330  	}
   331  }
   332  
   333  func (s *ContainerSetupSuite) TestContainerInitialised(c *gc.C) {
   334  	for _, test := range []struct {
   335  		ctype    instance.ContainerType
   336  		packages [][]string
   337  	}{
   338  		{instance.LXC, [][]string{
   339  			[]string{"--target-release", "precise-updates/cloud-tools", "lxc"},
   340  			[]string{"--target-release", "precise-updates/cloud-tools", "cloud-image-utils"}}},
   341  		{instance.KVM, [][]string{
   342  			[]string{"uvtool-libvirt"},
   343  			[]string{"uvtool"}}},
   344  	} {
   345  		s.assertContainerInitialised(c, test.ctype, test.packages, false)
   346  	}
   347  }
   348  
   349  func (s *ContainerSetupSuite) TestContainerInitLockError(c *gc.C) {
   350  	m, err := s.BackingState.AddOneMachine(state.MachineTemplate{
   351  		Series:      coretesting.FakeDefaultSeries,
   352  		Jobs:        []state.MachineJob{state.JobHostUnits},
   353  		Constraints: s.defaultConstraints,
   354  	})
   355  	c.Assert(err, jc.ErrorIsNil)
   356  	err = m.SetAgentVersion(version.Current)
   357  	c.Assert(err, jc.ErrorIsNil)
   358  
   359  	err = os.RemoveAll(s.initLockDir)
   360  	c.Assert(err, jc.ErrorIsNil)
   361  	handler, runner := s.setupContainerWorker(c, m.Tag().(names.MachineTag))
   362  	runner.Kill()
   363  	err = runner.Wait()
   364  	c.Assert(err, jc.ErrorIsNil)
   365  
   366  	_, err = handler.SetUp()
   367  	c.Assert(err, jc.ErrorIsNil)
   368  	err = handler.Handle([]string{"0/lxc/0"})
   369  	c.Assert(err, gc.ErrorMatches, ".*failed to acquire initialization lock:.*")
   370  
   371  }
   372  
   373  func (s *ContainerSetupSuite) TestMaybeOverrideDefaultLXCNet(c *gc.C) {
   374  	for i, test := range []struct {
   375  		ctype          instance.ContainerType
   376  		addressable    bool
   377  		expectOverride bool
   378  	}{
   379  		{instance.KVM, false, false},
   380  		{instance.KVM, true, false},
   381  		{instance.LXC, false, false},
   382  		{instance.LXC, true, true}, // the only case when we override; also last
   383  	} {
   384  		c.Logf(
   385  			"test %d: ctype: %q, addressable: %v -> expectOverride: %v",
   386  			i, test.ctype, test.addressable, test.expectOverride,
   387  		)
   388  		err := provisioner.MaybeOverrideDefaultLXCNet(test.ctype, test.addressable)
   389  		if !c.Check(err, jc.ErrorIsNil) {
   390  			continue
   391  		}
   392  		if !test.expectOverride {
   393  			c.Check(s.fakeLXCNet, jc.DoesNotExist)
   394  		} else {
   395  			AssertFileContains(c, s.fakeLXCNet, provisioner.EtcDefaultLXCNet)
   396  		}
   397  	}
   398  }
   399  
   400  func AssertFileContains(c *gc.C, filename string, expectedContent ...string) {
   401  	// TODO(dimitern): We should put this in juju/testing repo and
   402  	// replace all similar checks with it.
   403  	data, err := ioutil.ReadFile(filename)
   404  	c.Assert(err, jc.ErrorIsNil)
   405  	for _, s := range expectedContent {
   406  		c.Assert(string(data), jc.Contains, s)
   407  	}
   408  }
   409  
   410  func AssertFileContents(c *gc.C, checker gc.Checker, filename string, expectedContent ...string) {
   411  	// TODO(dimitern): We should put this in juju/testing repo and
   412  	// replace all similar checks with it.
   413  	data, err := ioutil.ReadFile(filename)
   414  	c.Assert(err, jc.ErrorIsNil)
   415  	for _, s := range expectedContent {
   416  		c.Assert(string(data), checker, s)
   417  	}
   418  }
   419  
   420  type SetIPAndARPForwardingSuite struct {
   421  	coretesting.BaseSuite
   422  }
   423  
   424  func (s *SetIPAndARPForwardingSuite) SetUpSuite(c *gc.C) {
   425  	if runtime.GOOS == "windows" {
   426  		c.Skip("bug 1403084: Skipping for now")
   427  	}
   428  	s.BaseSuite.SetUpSuite(c)
   429  }
   430  
   431  var _ = gc.Suite(&SetIPAndARPForwardingSuite{})
   432  
   433  func (s *SetIPAndARPForwardingSuite) TestSuccess(c *gc.C) {
   434  	// NOTE: Because PatchExecutableAsEchoArgs does not allow us to
   435  	// assert on earlier invocations of the same binary (each run
   436  	// overwrites the last args used), we only check sysctl was called
   437  	// for the second key (arpProxySysctlKey). We do check the config
   438  	// contains both though.
   439  	fakeConfig := filepath.Join(c.MkDir(), "sysctl.conf")
   440  	testing.PatchExecutableAsEchoArgs(c, s, "sysctl")
   441  	s.PatchValue(provisioner.SysctlConfig, fakeConfig)
   442  
   443  	err := provisioner.SetIPAndARPForwarding(true)
   444  	c.Assert(err, jc.ErrorIsNil)
   445  	expectConf := fmt.Sprintf(
   446  		"%s=1\n%s=1",
   447  		provisioner.IPForwardSysctlKey,
   448  		provisioner.ARPProxySysctlKey,
   449  	)
   450  	AssertFileContains(c, fakeConfig, expectConf)
   451  	expectKeyVal := fmt.Sprintf("%s=1", provisioner.IPForwardSysctlKey)
   452  	testing.AssertEchoArgs(c, "sysctl", "-w", expectKeyVal)
   453  	expectKeyVal = fmt.Sprintf("%s=1", provisioner.ARPProxySysctlKey)
   454  	testing.AssertEchoArgs(c, "sysctl", "-w", expectKeyVal)
   455  
   456  	err = provisioner.SetIPAndARPForwarding(false)
   457  	c.Assert(err, jc.ErrorIsNil)
   458  	expectConf = fmt.Sprintf(
   459  		"%s=0\n%s=0",
   460  		provisioner.IPForwardSysctlKey,
   461  		provisioner.ARPProxySysctlKey,
   462  	)
   463  	AssertFileContains(c, fakeConfig, expectConf)
   464  	expectKeyVal = fmt.Sprintf("%s=0", provisioner.IPForwardSysctlKey)
   465  	testing.AssertEchoArgs(c, "sysctl", "-w", expectKeyVal)
   466  	expectKeyVal = fmt.Sprintf("%s=0", provisioner.ARPProxySysctlKey)
   467  	testing.AssertEchoArgs(c, "sysctl", "-w", expectKeyVal)
   468  }
   469  
   470  func (s *SetIPAndARPForwardingSuite) TestFailure(c *gc.C) {
   471  	fakeConfig := filepath.Join(c.MkDir(), "sysctl.conf")
   472  	testing.PatchExecutableThrowError(c, s, "sysctl", 123)
   473  	s.PatchValue(provisioner.SysctlConfig, fakeConfig)
   474  	expectKeyVal := fmt.Sprintf("%s=1", provisioner.IPForwardSysctlKey)
   475  
   476  	err := provisioner.SetIPAndARPForwarding(true)
   477  	c.Assert(err, gc.ErrorMatches, fmt.Sprintf(
   478  		`cannot set %s: unexpected exit code 123`, expectKeyVal),
   479  	)
   480  	_, err = os.Stat(fakeConfig)
   481  	c.Assert(err, jc.Satisfies, os.IsNotExist)
   482  }
   483  
   484  type toolsFinderFunc func(v version.Number, series string, arch *string) (tools.List, error)
   485  
   486  func (t toolsFinderFunc) FindTools(v version.Number, series string, arch *string) (tools.List, error) {
   487  	return t(v, series, arch)
   488  }
   489  
   490  // AddressableContainerSetupSuite only contains tests depending on the
   491  // address allocation feature flag being enabled.
   492  type AddressableContainerSetupSuite struct {
   493  	ContainerSetupSuite
   494  }
   495  
   496  var _ = gc.Suite(&AddressableContainerSetupSuite{})
   497  
   498  func (s *AddressableContainerSetupSuite) enableFeatureFlag() {
   499  	s.SetFeatureFlags(feature.AddressAllocation)
   500  	featureflag.SetFlagsFromEnvironment(osenv.JujuFeatureFlagEnvKey)
   501  }
   502  
   503  func (s *AddressableContainerSetupSuite) TestContainerInitialised(c *gc.C) {
   504  	for _, test := range []struct {
   505  		ctype    instance.ContainerType
   506  		packages [][]string
   507  	}{
   508  		{instance.LXC, [][]string{{"--target-release", "precise-updates/cloud-tools", "lxc"}, {"--target-release", "precise-updates/cloud-tools", "cloud-image-utils"}}},
   509  		{instance.KVM, [][]string{{"uvtool-libvirt"}, {"uvtool"}}},
   510  	} {
   511  		s.enableFeatureFlag()
   512  		s.assertContainerInitialised(c, test.ctype, test.packages, true)
   513  	}
   514  }
   515  
   516  // LXCDefaultMTUSuite only contains tests depending on the
   517  // lxc-default-mtu environment setting being set explicitly.
   518  type LXCDefaultMTUSuite struct {
   519  	ContainerSetupSuite
   520  }
   521  
   522  var _ = gc.Suite(&LXCDefaultMTUSuite{})
   523  
   524  func (s *LXCDefaultMTUSuite) SetUpTest(c *gc.C) {
   525  	// Explicitly set lxc-default-mtu before JujuConnSuite constructs
   526  	// the environment, as the setting is immutable.
   527  	s.DummyConfig = dummy.SampleConfig()
   528  	s.DummyConfig["lxc-default-mtu"] = 9000
   529  	s.ContainerSetupSuite.SetUpTest(c)
   530  }
   531  
   532  func (s *LXCDefaultMTUSuite) TestDefaultMTUPropagatedToNewLXCBroker(c *gc.C) {
   533  	// create a machine to host the container.
   534  	m, err := s.BackingState.AddOneMachine(state.MachineTemplate{
   535  		Series:      coretesting.FakeDefaultSeries,
   536  		Jobs:        []state.MachineJob{state.JobHostUnits},
   537  		Constraints: s.defaultConstraints,
   538  	})
   539  	c.Assert(err, jc.ErrorIsNil)
   540  	err = m.SetSupportedContainers([]instance.ContainerType{instance.LXC, instance.KVM})
   541  	c.Assert(err, jc.ErrorIsNil)
   542  	err = m.SetAgentVersion(version.Current)
   543  	c.Assert(err, jc.ErrorIsNil)
   544  
   545  	brokerCalled := false
   546  	newlxcbroker := func(api provisioner.APICalls, agentConfig agent.Config, managerConfig container.ManagerConfig, imageURLGetter container.ImageURLGetter, enableNAT bool, defaultMTU int) (environs.InstanceBroker, error) {
   547  		brokerCalled = true
   548  		c.Assert(defaultMTU, gc.Equals, 9000)
   549  		return nil, fmt.Errorf("lxc broker error")
   550  	}
   551  	s.PatchValue(&provisioner.NewLxcBroker, newlxcbroker)
   552  	s.createContainer(c, m, instance.LXC)
   553  	c.Assert(brokerCalled, jc.IsTrue)
   554  }