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