github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/state/api/provisioner/provisioner_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 stdtesting "testing" 8 9 gc "launchpad.net/gocheck" 10 11 "launchpad.net/juju-core/constraints" 12 "launchpad.net/juju-core/errors" 13 "launchpad.net/juju-core/instance" 14 "launchpad.net/juju-core/juju/testing" 15 "launchpad.net/juju-core/state" 16 "launchpad.net/juju-core/state/api" 17 commontesting "launchpad.net/juju-core/state/api/common/testing" 18 "launchpad.net/juju-core/state/api/params" 19 "launchpad.net/juju-core/state/api/provisioner" 20 statetesting "launchpad.net/juju-core/state/testing" 21 coretesting "launchpad.net/juju-core/testing" 22 jc "launchpad.net/juju-core/testing/checkers" 23 "launchpad.net/juju-core/tools" 24 "launchpad.net/juju-core/utils" 25 "launchpad.net/juju-core/version" 26 ) 27 28 func TestAll(t *stdtesting.T) { 29 coretesting.MgoTestPackage(t) 30 } 31 32 type provisionerSuite struct { 33 testing.JujuConnSuite 34 *commontesting.EnvironWatcherTest 35 36 st *api.State 37 machine *state.Machine 38 39 provisioner *provisioner.State 40 } 41 42 var _ = gc.Suite(&provisionerSuite{}) 43 44 func (s *provisionerSuite) SetUpTest(c *gc.C) { 45 s.JujuConnSuite.SetUpTest(c) 46 47 var err error 48 s.machine, err = s.State.AddMachine("quantal", state.JobManageEnviron) 49 c.Assert(err, gc.IsNil) 50 password, err := utils.RandomPassword() 51 c.Assert(err, gc.IsNil) 52 err = s.machine.SetPassword(password) 53 c.Assert(err, gc.IsNil) 54 err = s.machine.SetProvisioned("i-manager", "fake_nonce", nil) 55 c.Assert(err, gc.IsNil) 56 s.st = s.OpenAPIAsMachine(c, s.machine.Tag(), password, "fake_nonce") 57 c.Assert(s.st, gc.NotNil) 58 59 // Create the provisioner API facade. 60 s.provisioner = s.st.Provisioner() 61 c.Assert(s.provisioner, gc.NotNil) 62 63 s.EnvironWatcherTest = commontesting.NewEnvironWatcherTest(s.provisioner, s.State, s.BackingState, commontesting.HasSecrets) 64 } 65 66 func (s *provisionerSuite) TestMachineTagAndId(c *gc.C) { 67 apiMachine, err := s.provisioner.Machine("machine-42") 68 c.Assert(err, gc.ErrorMatches, "machine 42 not found") 69 c.Assert(err, jc.Satisfies, params.IsCodeNotFound) 70 c.Assert(apiMachine, gc.IsNil) 71 72 apiMachine, err = s.provisioner.Machine(s.machine.Tag()) 73 c.Assert(err, gc.IsNil) 74 c.Assert(apiMachine.Tag(), gc.Equals, s.machine.Tag()) 75 c.Assert(apiMachine.Id(), gc.Equals, s.machine.Id()) 76 } 77 78 func (s *provisionerSuite) TestGetSetStatus(c *gc.C) { 79 apiMachine, err := s.provisioner.Machine(s.machine.Tag()) 80 c.Assert(err, gc.IsNil) 81 82 status, info, err := apiMachine.Status() 83 c.Assert(err, gc.IsNil) 84 c.Assert(status, gc.Equals, params.StatusPending) 85 c.Assert(info, gc.Equals, "") 86 87 err = apiMachine.SetStatus(params.StatusStarted, "blah") 88 c.Assert(err, gc.IsNil) 89 90 status, info, err = apiMachine.Status() 91 c.Assert(err, gc.IsNil) 92 c.Assert(status, gc.Equals, params.StatusStarted) 93 c.Assert(info, gc.Equals, "blah") 94 } 95 96 func (s *provisionerSuite) TestEnsureDeadAndRemove(c *gc.C) { 97 // Create a fresh machine to test the complete scenario. 98 otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits) 99 c.Assert(err, gc.IsNil) 100 c.Assert(otherMachine.Life(), gc.Equals, state.Alive) 101 102 apiMachine, err := s.provisioner.Machine(otherMachine.Tag()) 103 c.Assert(err, gc.IsNil) 104 105 err = apiMachine.Remove() 106 c.Assert(err, gc.ErrorMatches, `cannot remove entity "machine-1": still alive`) 107 err = apiMachine.EnsureDead() 108 c.Assert(err, gc.IsNil) 109 110 err = otherMachine.Refresh() 111 c.Assert(err, gc.IsNil) 112 c.Assert(otherMachine.Life(), gc.Equals, state.Dead) 113 114 err = apiMachine.EnsureDead() 115 c.Assert(err, gc.IsNil) 116 err = otherMachine.Refresh() 117 c.Assert(err, gc.IsNil) 118 c.Assert(otherMachine.Life(), gc.Equals, state.Dead) 119 120 err = apiMachine.Remove() 121 c.Assert(err, gc.IsNil) 122 err = otherMachine.Refresh() 123 c.Assert(err, jc.Satisfies, errors.IsNotFoundError) 124 125 err = apiMachine.EnsureDead() 126 c.Assert(err, gc.ErrorMatches, "machine 1 not found") 127 c.Assert(err, jc.Satisfies, params.IsCodeNotFound) 128 129 // Now try to EnsureDead machine 0 - should fail. 130 apiMachine, err = s.provisioner.Machine(s.machine.Tag()) 131 c.Assert(err, gc.IsNil) 132 err = apiMachine.EnsureDead() 133 c.Assert(err, gc.ErrorMatches, "machine 0 is required by the environment") 134 } 135 136 func (s *provisionerSuite) TestRefreshAndLife(c *gc.C) { 137 // Create a fresh machine to test the complete scenario. 138 otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits) 139 c.Assert(err, gc.IsNil) 140 c.Assert(otherMachine.Life(), gc.Equals, state.Alive) 141 142 apiMachine, err := s.provisioner.Machine(otherMachine.Tag()) 143 c.Assert(err, gc.IsNil) 144 c.Assert(apiMachine.Life(), gc.Equals, params.Alive) 145 146 err = apiMachine.EnsureDead() 147 c.Assert(err, gc.IsNil) 148 c.Assert(apiMachine.Life(), gc.Equals, params.Alive) 149 150 err = apiMachine.Refresh() 151 c.Assert(err, gc.IsNil) 152 c.Assert(apiMachine.Life(), gc.Equals, params.Dead) 153 } 154 155 func (s *provisionerSuite) TestSetProvisionedAndInstanceId(c *gc.C) { 156 // Create a fresh machine, since machine 0 is already provisioned. 157 notProvisionedMachine, err := s.State.AddMachine("quantal", state.JobHostUnits) 158 c.Assert(err, gc.IsNil) 159 160 apiMachine, err := s.provisioner.Machine(notProvisionedMachine.Tag()) 161 c.Assert(err, gc.IsNil) 162 163 instanceId, err := apiMachine.InstanceId() 164 c.Assert(err, jc.Satisfies, params.IsCodeNotProvisioned) 165 c.Assert(err, gc.ErrorMatches, "machine 1 is not provisioned") 166 c.Assert(instanceId, gc.Equals, instance.Id("")) 167 168 hwChars := instance.MustParseHardware("cpu-cores=123", "mem=4G") 169 err = apiMachine.SetProvisioned("i-will", "fake_nonce", &hwChars) 170 c.Assert(err, gc.IsNil) 171 172 instanceId, err = apiMachine.InstanceId() 173 c.Assert(err, gc.IsNil) 174 c.Assert(instanceId, gc.Equals, instance.Id("i-will")) 175 176 // Try it again - should fail. 177 err = apiMachine.SetProvisioned("i-wont", "fake", nil) 178 c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": already set`) 179 180 // Now try to get machine 0's instance id. 181 apiMachine, err = s.provisioner.Machine(s.machine.Tag()) 182 c.Assert(err, gc.IsNil) 183 instanceId, err = apiMachine.InstanceId() 184 c.Assert(err, gc.IsNil) 185 c.Assert(instanceId, gc.Equals, instance.Id("i-manager")) 186 } 187 188 func (s *provisionerSuite) TestSeries(c *gc.C) { 189 // Create a fresh machine with different series. 190 foobarMachine, err := s.State.AddMachine("foobar", state.JobHostUnits) 191 c.Assert(err, gc.IsNil) 192 193 apiMachine, err := s.provisioner.Machine(foobarMachine.Tag()) 194 c.Assert(err, gc.IsNil) 195 series, err := apiMachine.Series() 196 c.Assert(err, gc.IsNil) 197 c.Assert(series, gc.Equals, "foobar") 198 199 // Now try machine 0. 200 apiMachine, err = s.provisioner.Machine(s.machine.Tag()) 201 c.Assert(err, gc.IsNil) 202 series, err = apiMachine.Series() 203 c.Assert(err, gc.IsNil) 204 c.Assert(series, gc.Equals, "quantal") 205 } 206 207 func (s *provisionerSuite) TestConstraints(c *gc.C) { 208 // Create a fresh machine with some constraints. 209 template := state.MachineTemplate{ 210 Series: "quantal", 211 Jobs: []state.MachineJob{state.JobHostUnits}, 212 Constraints: constraints.MustParse("cpu-cores=12", "mem=8G"), 213 } 214 consMachine, err := s.State.AddOneMachine(template) 215 c.Assert(err, gc.IsNil) 216 217 apiMachine, err := s.provisioner.Machine(consMachine.Tag()) 218 c.Assert(err, gc.IsNil) 219 cons, err := apiMachine.Constraints() 220 c.Assert(err, gc.IsNil) 221 c.Assert(cons, gc.DeepEquals, template.Constraints) 222 223 // Now try machine 0. 224 apiMachine, err = s.provisioner.Machine(s.machine.Tag()) 225 c.Assert(err, gc.IsNil) 226 cons, err = apiMachine.Constraints() 227 c.Assert(err, gc.IsNil) 228 c.Assert(cons, gc.DeepEquals, constraints.Value{}) 229 } 230 231 func (s *provisionerSuite) TestWatchContainers(c *gc.C) { 232 apiMachine, err := s.provisioner.Machine(s.machine.Tag()) 233 c.Assert(err, gc.IsNil) 234 235 // Add one LXC container. 236 template := state.MachineTemplate{ 237 Series: "quantal", 238 Jobs: []state.MachineJob{state.JobHostUnits}, 239 } 240 container, err := s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC) 241 c.Assert(err, gc.IsNil) 242 243 w, err := apiMachine.WatchContainers(instance.LXC) 244 c.Assert(err, gc.IsNil) 245 defer statetesting.AssertStop(c, w) 246 wc := statetesting.NewStringsWatcherC(c, s.BackingState, w) 247 248 // Initial event. 249 wc.AssertChange(container.Id()) 250 251 // Change something other than the containers and make sure it's 252 // not detected. 253 err = apiMachine.SetStatus(params.StatusStarted, "not really") 254 c.Assert(err, gc.IsNil) 255 wc.AssertNoChange() 256 257 // Add a KVM container and make sure it's not detected. 258 container, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.KVM) 259 c.Assert(err, gc.IsNil) 260 wc.AssertNoChange() 261 262 // Add another LXC container and make sure it's detected. 263 container, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC) 264 c.Assert(err, gc.IsNil) 265 wc.AssertChange(container.Id()) 266 267 statetesting.AssertStop(c, w) 268 wc.AssertClosed() 269 } 270 271 func (s *provisionerSuite) TestWatchContainersAcceptsSupportedContainers(c *gc.C) { 272 apiMachine, err := s.provisioner.Machine(s.machine.Tag()) 273 c.Assert(err, gc.IsNil) 274 275 for _, ctype := range instance.ContainerTypes { 276 w, err := apiMachine.WatchContainers(ctype) 277 c.Assert(w, gc.NotNil) 278 c.Assert(err, gc.IsNil) 279 } 280 } 281 282 func (s *provisionerSuite) TestWatchContainersErrors(c *gc.C) { 283 apiMachine, err := s.provisioner.Machine(s.machine.Tag()) 284 c.Assert(err, gc.IsNil) 285 286 _, err = apiMachine.WatchContainers(instance.NONE) 287 c.Assert(err, gc.ErrorMatches, `unsupported container type "none"`) 288 289 _, err = apiMachine.WatchContainers("") 290 c.Assert(err, gc.ErrorMatches, "container type must be specified") 291 } 292 293 func (s *provisionerSuite) TestWatchEnvironMachines(c *gc.C) { 294 w, err := s.provisioner.WatchEnvironMachines() 295 c.Assert(err, gc.IsNil) 296 defer statetesting.AssertStop(c, w) 297 wc := statetesting.NewStringsWatcherC(c, s.BackingState, w) 298 299 // Initial event. 300 wc.AssertChange(s.machine.Id()) 301 302 // Add another 2 machines make sure they are detected. 303 otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits) 304 c.Assert(err, gc.IsNil) 305 otherMachine, err = s.State.AddMachine("quantal", state.JobHostUnits) 306 c.Assert(err, gc.IsNil) 307 wc.AssertChange("1", "2") 308 309 // Change the lifecycle of last machine. 310 err = otherMachine.EnsureDead() 311 c.Assert(err, gc.IsNil) 312 wc.AssertChange("2") 313 314 // Add a container and make sure it's not detected. 315 template := state.MachineTemplate{ 316 Series: "quantal", 317 Jobs: []state.MachineJob{state.JobHostUnits}, 318 } 319 _, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC) 320 c.Assert(err, gc.IsNil) 321 wc.AssertNoChange() 322 323 statetesting.AssertStop(c, w) 324 wc.AssertClosed() 325 } 326 327 func (s *provisionerSuite) TestStateAddresses(c *gc.C) { 328 err := s.machine.SetAddresses([]instance.Address{ 329 instance.NewAddress("0.1.2.3"), 330 }) 331 c.Assert(err, gc.IsNil) 332 333 stateAddresses, err := s.State.Addresses() 334 c.Assert(err, gc.IsNil) 335 336 addresses, err := s.provisioner.StateAddresses() 337 c.Assert(err, gc.IsNil) 338 c.Assert(addresses, gc.DeepEquals, stateAddresses) 339 } 340 341 func (s *provisionerSuite) TestAPIAddresses(c *gc.C) { 342 err := s.machine.SetAddresses([]instance.Address{ 343 instance.NewAddress("0.1.2.3"), 344 }) 345 c.Assert(err, gc.IsNil) 346 347 apiAddresses, err := s.State.APIAddresses() 348 c.Assert(err, gc.IsNil) 349 350 addresses, err := s.provisioner.APIAddresses() 351 c.Assert(err, gc.IsNil) 352 c.Assert(addresses, gc.DeepEquals, apiAddresses) 353 } 354 355 func (s *provisionerSuite) TestContainerConfig(c *gc.C) { 356 result, err := s.provisioner.ContainerConfig() 357 c.Assert(err, gc.IsNil) 358 c.Assert(result.ProviderType, gc.Equals, "dummy") 359 c.Assert(result.AuthorizedKeys, gc.Equals, coretesting.FakeAuthKeys) 360 c.Assert(result.SSLHostnameVerification, jc.IsTrue) 361 } 362 363 func (s *provisionerSuite) TestCACert(c *gc.C) { 364 caCert, err := s.provisioner.CACert() 365 c.Assert(err, gc.IsNil) 366 c.Assert(caCert, gc.DeepEquals, s.State.CACert()) 367 } 368 369 func (s *provisionerSuite) TestToolsWrongMachine(c *gc.C) { 370 tools, err := s.provisioner.Tools("42") 371 c.Assert(err, gc.ErrorMatches, "permission denied") 372 c.Assert(err, jc.Satisfies, params.IsCodeUnauthorized) 373 c.Assert(tools, gc.IsNil) 374 } 375 376 func (s *provisionerSuite) TestTools(c *gc.C) { 377 cur := version.Current 378 curTools := &tools.Tools{Version: cur, URL: ""} 379 curTools.Version.Minor++ 380 s.machine.SetAgentVersion(cur) 381 // Provisioner.Tools returns the *desired* set of tools, not the 382 // currently running set. We want to be upgraded to cur.Version 383 stateTools, err := s.provisioner.Tools(s.machine.Tag()) 384 c.Assert(err, gc.IsNil) 385 c.Assert(stateTools.Version, gc.Equals, cur) 386 c.Assert(stateTools.URL, gc.Not(gc.Equals), "") 387 } 388 389 func (s *provisionerSuite) TestSetSupportedContainers(c *gc.C) { 390 apiMachine, err := s.provisioner.Machine(s.machine.Tag()) 391 c.Assert(err, gc.IsNil) 392 err = apiMachine.SetSupportedContainers(instance.LXC, instance.KVM) 393 c.Assert(err, gc.IsNil) 394 395 err = s.machine.Refresh() 396 c.Assert(err, gc.IsNil) 397 containers, ok := s.machine.SupportedContainers() 398 c.Assert(ok, jc.IsTrue) 399 c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC, instance.KVM}) 400 } 401 402 func (s *provisionerSuite) TestSupportsNoContainers(c *gc.C) { 403 apiMachine, err := s.provisioner.Machine(s.machine.Tag()) 404 c.Assert(err, gc.IsNil) 405 err = apiMachine.SupportsNoContainers() 406 c.Assert(err, gc.IsNil) 407 408 err = s.machine.Refresh() 409 c.Assert(err, gc.IsNil) 410 containers, ok := s.machine.SupportedContainers() 411 c.Assert(ok, jc.IsTrue) 412 c.Assert(containers, gc.DeepEquals, []instance.ContainerType{}) 413 }