github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/worker/provisioner/kvm-broker_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package provisioner_test 5 6 import ( 7 "fmt" 8 "path/filepath" 9 "time" 10 11 "github.com/juju/errors" 12 "github.com/juju/names" 13 jc "github.com/juju/testing/checkers" 14 gc "launchpad.net/gocheck" 15 16 "github.com/juju/juju/agent" 17 "github.com/juju/juju/constraints" 18 "github.com/juju/juju/container" 19 "github.com/juju/juju/container/kvm/mock" 20 kvmtesting "github.com/juju/juju/container/kvm/testing" 21 "github.com/juju/juju/environs" 22 "github.com/juju/juju/instance" 23 instancetest "github.com/juju/juju/instance/testing" 24 jujutesting "github.com/juju/juju/juju/testing" 25 "github.com/juju/juju/network" 26 "github.com/juju/juju/state" 27 coretesting "github.com/juju/juju/testing" 28 coretools "github.com/juju/juju/tools" 29 "github.com/juju/juju/version" 30 "github.com/juju/juju/worker/provisioner" 31 ) 32 33 type kvmSuite struct { 34 kvmtesting.TestSuite 35 events chan mock.Event 36 } 37 38 type kvmBrokerSuite struct { 39 kvmSuite 40 broker environs.InstanceBroker 41 agentConfig agent.Config 42 } 43 44 var _ = gc.Suite(&kvmBrokerSuite{}) 45 46 func (s *kvmSuite) SetUpTest(c *gc.C) { 47 s.TestSuite.SetUpTest(c) 48 s.events = make(chan mock.Event) 49 go func() { 50 for event := range s.events { 51 c.Output(3, fmt.Sprintf("kvm event: <%s, %s>", event.Action, event.InstanceId)) 52 } 53 }() 54 s.TestSuite.ContainerFactory.AddListener(s.events) 55 } 56 57 func (s *kvmSuite) TearDownTest(c *gc.C) { 58 close(s.events) 59 s.TestSuite.TearDownTest(c) 60 } 61 62 func (s *kvmBrokerSuite) SetUpTest(c *gc.C) { 63 s.kvmSuite.SetUpTest(c) 64 tools := &coretools.Tools{ 65 Version: version.MustParseBinary("2.3.4-foo-bar"), 66 URL: "http://tools.testing.invalid/2.3.4-foo-bar.tgz", 67 } 68 var err error 69 s.agentConfig, err = agent.NewAgentConfig( 70 agent.AgentConfigParams{ 71 DataDir: "/not/used/here", 72 Tag: "tag", 73 UpgradedToVersion: version.Current.Number, 74 Password: "dummy-secret", 75 Nonce: "nonce", 76 APIAddresses: []string{"10.0.0.1:1234"}, 77 CACert: coretesting.CACert, 78 }) 79 c.Assert(err, gc.IsNil) 80 managerConfig := container.ManagerConfig{container.ConfigName: "juju"} 81 s.broker, err = provisioner.NewKvmBroker(&fakeAPI{}, tools, s.agentConfig, managerConfig) 82 c.Assert(err, gc.IsNil) 83 } 84 85 func (s *kvmBrokerSuite) startInstance(c *gc.C, machineId string) instance.Instance { 86 machineNonce := "fake-nonce" 87 stateInfo := jujutesting.FakeStateInfo(machineId) 88 apiInfo := jujutesting.FakeAPIInfo(machineId) 89 machineConfig := environs.NewMachineConfig(machineId, machineNonce, nil, stateInfo, apiInfo) 90 cons := constraints.Value{} 91 possibleTools := s.broker.(coretools.HasTools).Tools("precise") 92 kvm, _, _, err := s.broker.StartInstance(environs.StartInstanceParams{ 93 Constraints: cons, 94 Tools: possibleTools, 95 MachineConfig: machineConfig, 96 }) 97 c.Assert(err, gc.IsNil) 98 return kvm 99 } 100 101 func (s *kvmBrokerSuite) TestStopInstance(c *gc.C) { 102 kvm0 := s.startInstance(c, "1/kvm/0") 103 kvm1 := s.startInstance(c, "1/kvm/1") 104 kvm2 := s.startInstance(c, "1/kvm/2") 105 106 err := s.broker.StopInstances(kvm0.Id()) 107 c.Assert(err, gc.IsNil) 108 s.assertInstances(c, kvm1, kvm2) 109 c.Assert(s.kvmContainerDir(kvm0), jc.DoesNotExist) 110 c.Assert(s.kvmRemovedContainerDir(kvm0), jc.IsDirectory) 111 112 err = s.broker.StopInstances(kvm1.Id(), kvm2.Id()) 113 c.Assert(err, gc.IsNil) 114 s.assertInstances(c) 115 } 116 117 func (s *kvmBrokerSuite) TestAllInstances(c *gc.C) { 118 kvm0 := s.startInstance(c, "1/kvm/0") 119 kvm1 := s.startInstance(c, "1/kvm/1") 120 s.assertInstances(c, kvm0, kvm1) 121 122 err := s.broker.StopInstances(kvm1.Id()) 123 c.Assert(err, gc.IsNil) 124 kvm2 := s.startInstance(c, "1/kvm/2") 125 s.assertInstances(c, kvm0, kvm2) 126 } 127 128 func (s *kvmBrokerSuite) assertInstances(c *gc.C, inst ...instance.Instance) { 129 results, err := s.broker.AllInstances() 130 c.Assert(err, gc.IsNil) 131 instancetest.MatchInstances(c, results, inst...) 132 } 133 134 func (s *kvmBrokerSuite) kvmContainerDir(inst instance.Instance) string { 135 return filepath.Join(s.ContainerDir, string(inst.Id())) 136 } 137 138 func (s *kvmBrokerSuite) kvmRemovedContainerDir(inst instance.Instance) string { 139 return filepath.Join(s.RemovedDir, string(inst.Id())) 140 } 141 142 type kvmProvisionerSuite struct { 143 CommonProvisionerSuite 144 kvmSuite 145 machineId string 146 events chan mock.Event 147 } 148 149 var _ = gc.Suite(&kvmProvisionerSuite{}) 150 151 func (s *kvmProvisionerSuite) SetUpSuite(c *gc.C) { 152 s.CommonProvisionerSuite.SetUpSuite(c) 153 s.kvmSuite.SetUpSuite(c) 154 } 155 156 func (s *kvmProvisionerSuite) TearDownSuite(c *gc.C) { 157 s.kvmSuite.TearDownSuite(c) 158 s.CommonProvisionerSuite.TearDownSuite(c) 159 } 160 161 func (s *kvmProvisionerSuite) SetUpTest(c *gc.C) { 162 s.CommonProvisionerSuite.SetUpTest(c) 163 s.kvmSuite.SetUpTest(c) 164 165 // The kvm provisioner actually needs the machine it is being created on 166 // to be in state, in order to get the watcher. 167 m, err := s.State.AddMachine(coretesting.FakeDefaultSeries, state.JobHostUnits, state.JobManageEnviron) 168 c.Assert(err, gc.IsNil) 169 err = m.SetAddresses(network.NewAddress("0.1.2.3", network.ScopeUnknown)) 170 c.Assert(err, gc.IsNil) 171 172 hostPorts := [][]network.HostPort{{{ 173 Address: network.NewAddress("0.1.2.3", network.ScopeUnknown), 174 Port: 1234, 175 }}} 176 err = s.State.SetAPIHostPorts(hostPorts) 177 c.Assert(err, gc.IsNil) 178 179 s.machineId = m.Id() 180 s.APILogin(c, m) 181 err = m.SetAgentVersion(version.Current) 182 c.Assert(err, gc.IsNil) 183 184 s.events = make(chan mock.Event, 25) 185 s.ContainerFactory.AddListener(s.events) 186 } 187 188 func (s *kvmProvisionerSuite) expectStarted(c *gc.C, machine *state.Machine) string { 189 s.State.StartSync() 190 event := <-s.events 191 c.Assert(event.Action, gc.Equals, mock.Started) 192 err := machine.Refresh() 193 c.Assert(err, gc.IsNil) 194 s.waitInstanceId(c, machine, instance.Id(event.InstanceId)) 195 return event.InstanceId 196 } 197 198 func (s *kvmProvisionerSuite) expectStopped(c *gc.C, instId string) { 199 s.State.StartSync() 200 event := <-s.events 201 c.Assert(event.Action, gc.Equals, mock.Stopped) 202 c.Assert(event.InstanceId, gc.Equals, instId) 203 } 204 205 func (s *kvmProvisionerSuite) expectNoEvents(c *gc.C) { 206 select { 207 case event := <-s.events: 208 c.Fatalf("unexpected event %#v", event) 209 case <-time.After(coretesting.ShortWait): 210 return 211 } 212 } 213 214 func (s *kvmProvisionerSuite) TearDownTest(c *gc.C) { 215 close(s.events) 216 s.kvmSuite.TearDownTest(c) 217 s.CommonProvisionerSuite.TearDownTest(c) 218 } 219 220 func (s *kvmProvisionerSuite) newKvmProvisioner(c *gc.C) provisioner.Provisioner { 221 machineTag := names.NewMachineTag(s.machineId).String() 222 agentConfig := s.AgentConfigForTag(c, machineTag) 223 tools, err := s.provisioner.Tools(agentConfig.Tag()) 224 c.Assert(err, gc.IsNil) 225 managerConfig := container.ManagerConfig{container.ConfigName: "juju"} 226 broker, err := provisioner.NewKvmBroker(s.provisioner, tools, agentConfig, managerConfig) 227 c.Assert(err, gc.IsNil) 228 return provisioner.NewContainerProvisioner(instance.KVM, s.provisioner, agentConfig, broker) 229 } 230 231 func (s *kvmProvisionerSuite) TestProvisionerStartStop(c *gc.C) { 232 p := s.newKvmProvisioner(c) 233 c.Assert(p.Stop(), gc.IsNil) 234 } 235 236 func (s *kvmProvisionerSuite) TestDoesNotStartEnvironMachines(c *gc.C) { 237 p := s.newKvmProvisioner(c) 238 defer stop(c, p) 239 240 // Check that an instance is not provisioned when the machine is created. 241 _, err := s.State.AddMachine(coretesting.FakeDefaultSeries, state.JobHostUnits) 242 c.Assert(err, gc.IsNil) 243 244 s.expectNoEvents(c) 245 } 246 247 func (s *kvmProvisionerSuite) TestDoesNotHaveRetryWatcher(c *gc.C) { 248 p := s.newKvmProvisioner(c) 249 defer stop(c, p) 250 251 w, err := provisioner.GetRetryWatcher(p) 252 c.Assert(w, gc.IsNil) 253 c.Assert(err, jc.Satisfies, errors.IsNotImplemented) 254 } 255 256 func (s *kvmProvisionerSuite) addContainer(c *gc.C) *state.Machine { 257 template := state.MachineTemplate{ 258 Series: coretesting.FakeDefaultSeries, 259 Jobs: []state.MachineJob{state.JobHostUnits}, 260 } 261 container, err := s.State.AddMachineInsideMachine(template, s.machineId, instance.KVM) 262 c.Assert(err, gc.IsNil) 263 return container 264 } 265 266 func (s *kvmProvisionerSuite) TestContainerStartedAndStopped(c *gc.C) { 267 p := s.newKvmProvisioner(c) 268 defer stop(c, p) 269 270 container := s.addContainer(c) 271 272 instId := s.expectStarted(c, container) 273 274 // ...and removed, along with the machine, when the machine is Dead. 275 c.Assert(container.EnsureDead(), gc.IsNil) 276 s.expectStopped(c, instId) 277 s.waitRemoved(c, container) 278 }