launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/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 gc "launchpad.net/gocheck" 9 "os/exec" 10 11 "launchpad.net/juju-core/agent" 12 "launchpad.net/juju-core/environs" 13 "launchpad.net/juju-core/environs/config" 14 "launchpad.net/juju-core/instance" 15 "launchpad.net/juju-core/state" 16 apiprovisioner "launchpad.net/juju-core/state/api/provisioner" 17 jc "launchpad.net/juju-core/testing/checkers" 18 "launchpad.net/juju-core/testing/testbase" 19 "launchpad.net/juju-core/utils" 20 "launchpad.net/juju-core/version" 21 "launchpad.net/juju-core/worker" 22 "launchpad.net/juju-core/worker/provisioner" 23 ) 24 25 type ContainerSetupSuite struct { 26 CommonProvisionerSuite 27 p provisioner.Provisioner 28 // Record the apt commands issued as part of container initialisation 29 aptCmdChan <-chan *exec.Cmd 30 } 31 32 var _ = gc.Suite(&ContainerSetupSuite{}) 33 34 func (s *ContainerSetupSuite) SetUpSuite(c *gc.C) { 35 s.CommonProvisionerSuite.SetUpSuite(c) 36 } 37 38 func (s *ContainerSetupSuite) TearDownSuite(c *gc.C) { 39 s.CommonProvisionerSuite.TearDownSuite(c) 40 } 41 42 func allFatal(error) bool { 43 return true 44 } 45 46 func noImportance(err0, err1 error) bool { 47 return false 48 } 49 50 func (s *ContainerSetupSuite) SetUpTest(c *gc.C) { 51 s.CommonProvisionerSuite.SetUpTest(c) 52 s.CommonProvisionerSuite.setupEnvironmentManager(c) 53 aptCmdChan, cleanup := testbase.HookCommandOutput(&utils.AptCommandOutput, []byte{}, nil) 54 s.aptCmdChan = aptCmdChan 55 s.AddCleanup(func(*gc.C) { cleanup() }) 56 57 // Set up provisioner for the state machine. 58 agentConfig := s.AgentConfigForTag(c, "machine-0") 59 s.p = provisioner.NewEnvironProvisioner(s.provisioner, agentConfig) 60 } 61 62 func (s *ContainerSetupSuite) TearDownTest(c *gc.C) { 63 stop(c, s.p) 64 s.CommonProvisionerSuite.TearDownTest(c) 65 } 66 67 func (s *ContainerSetupSuite) setupContainerWorker(c *gc.C, tag string) { 68 runner := worker.NewRunner(allFatal, noImportance) 69 pr := s.st.Provisioner() 70 machine, err := pr.Machine(tag) 71 c.Assert(err, gc.IsNil) 72 err = machine.SetSupportedContainers(instance.ContainerTypes...) 73 c.Assert(err, gc.IsNil) 74 cfg := s.AgentConfigForTag(c, tag) 75 76 watcherName := fmt.Sprintf("%s-container-watcher", machine.Id()) 77 handler := provisioner.NewContainerSetupHandler(runner, watcherName, instance.ContainerTypes, machine, pr, cfg) 78 runner.StartWorker(watcherName, func() (worker.Worker, error) { 79 return worker.NewStringsWorker(handler), nil 80 }) 81 go func() { 82 runner.Wait() 83 }() 84 } 85 86 func (s *ContainerSetupSuite) createContainer(c *gc.C, host *state.Machine, ctype instance.ContainerType) { 87 inst := s.checkStartInstance(c, host) 88 s.setupContainerWorker(c, host.Tag()) 89 90 // make a container on the host machine 91 template := state.MachineTemplate{ 92 Series: config.DefaultSeries, 93 Jobs: []state.MachineJob{state.JobHostUnits}, 94 } 95 container, err := s.State.AddMachineInsideMachine(template, host.Id(), ctype) 96 c.Assert(err, gc.IsNil) 97 98 // the host machine agent should not attempt to create the container 99 s.checkNoOperations(c) 100 101 // cleanup 102 c.Assert(container.EnsureDead(), gc.IsNil) 103 c.Assert(container.Remove(), gc.IsNil) 104 c.Assert(host.EnsureDead(), gc.IsNil) 105 s.checkStopInstances(c, inst) 106 s.waitRemoved(c, host) 107 } 108 109 func (s *ContainerSetupSuite) assertContainerProvisionerStarted( 110 c *gc.C, host *state.Machine, ctype instance.ContainerType) { 111 112 // A stub worker callback to record what happens. 113 provisionerStarted := false 114 startProvisionerWorker := func(runner worker.Runner, containerType instance.ContainerType, 115 pr *apiprovisioner.State, cfg agent.Config, broker environs.InstanceBroker) error { 116 c.Assert(containerType, gc.Equals, ctype) 117 c.Assert(cfg.Tag(), gc.Equals, host.Tag()) 118 provisionerStarted = true 119 return nil 120 } 121 s.PatchValue(&provisioner.StartProvisioner, startProvisionerWorker) 122 123 s.createContainer(c, host, ctype) 124 // Consume the apt command used to initialise the container. 125 <-s.aptCmdChan 126 127 // the container worker should have created the provisioner 128 c.Assert(provisionerStarted, jc.IsTrue) 129 } 130 131 func (s *ContainerSetupSuite) TestContainerProvisionerStarted(c *gc.C) { 132 for _, ctype := range instance.ContainerTypes { 133 // create a machine to host the container. 134 m, err := s.BackingState.AddOneMachine(state.MachineTemplate{ 135 Series: config.DefaultSeries, 136 Jobs: []state.MachineJob{state.JobHostUnits}, 137 Constraints: s.defaultConstraints, 138 }) 139 c.Assert(err, gc.IsNil) 140 err = m.SetSupportedContainers([]instance.ContainerType{instance.LXC, instance.KVM}) 141 c.Assert(err, gc.IsNil) 142 err = m.SetAgentVersion(version.Current) 143 c.Assert(err, gc.IsNil) 144 s.assertContainerProvisionerStarted(c, m, ctype) 145 } 146 } 147 148 func (s *ContainerSetupSuite) assertContainerInitialised(c *gc.C, ctype instance.ContainerType, packages []string) { 149 // A noop worker callback. 150 startProvisionerWorker := func(runner worker.Runner, containerType instance.ContainerType, 151 pr *apiprovisioner.State, cfg agent.Config, broker environs.InstanceBroker) error { 152 return nil 153 } 154 s.PatchValue(&provisioner.StartProvisioner, startProvisionerWorker) 155 156 // create a machine to host the container. 157 m, err := s.BackingState.AddOneMachine(state.MachineTemplate{ 158 Series: config.DefaultSeries, 159 Jobs: []state.MachineJob{state.JobHostUnits}, 160 Constraints: s.defaultConstraints, 161 }) 162 c.Assert(err, gc.IsNil) 163 err = m.SetSupportedContainers([]instance.ContainerType{instance.LXC, instance.KVM}) 164 c.Assert(err, gc.IsNil) 165 err = m.SetAgentVersion(version.Current) 166 c.Assert(err, gc.IsNil) 167 s.createContainer(c, m, ctype) 168 169 cmd := <-s.aptCmdChan 170 c.Assert(cmd.Env[len(cmd.Env)-1], gc.Equals, "DEBIAN_FRONTEND=noninteractive") 171 expected := []string{ 172 "apt-get", "--option=Dpkg::Options::=--force-confold", 173 "--option=Dpkg::options::=--force-unsafe-io", "--assume-yes", "--quiet", 174 "install"} 175 expected = append(expected, packages...) 176 c.Assert(cmd.Args, gc.DeepEquals, expected) 177 } 178 179 func (s *ContainerSetupSuite) TestContainerInitialised(c *gc.C) { 180 for _, test := range []struct { 181 ctype instance.ContainerType 182 packages []string 183 }{ 184 {instance.LXC, []string{"lxc"}}, 185 {instance.KVM, []string{"uvtool-libvirt", "uvtool"}}, 186 } { 187 s.assertContainerInitialised(c, test.ctype, test.packages) 188 } 189 }