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