github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/apiserver/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 "fmt" 8 stdtesting "testing" 9 10 "github.com/juju/errors" 11 "github.com/juju/names" 12 jc "github.com/juju/testing/checkers" 13 "github.com/juju/utils/proxy" 14 gc "gopkg.in/check.v1" 15 16 "github.com/juju/juju/apiserver/common" 17 commontesting "github.com/juju/juju/apiserver/common/testing" 18 "github.com/juju/juju/apiserver/params" 19 "github.com/juju/juju/apiserver/provisioner" 20 apiservertesting "github.com/juju/juju/apiserver/testing" 21 "github.com/juju/juju/constraints" 22 "github.com/juju/juju/container" 23 "github.com/juju/juju/instance" 24 "github.com/juju/juju/juju/testing" 25 "github.com/juju/juju/network" 26 "github.com/juju/juju/state" 27 "github.com/juju/juju/state/multiwatcher" 28 statetesting "github.com/juju/juju/state/testing" 29 "github.com/juju/juju/storage" 30 coretesting "github.com/juju/juju/testing" 31 ) 32 33 func Test(t *stdtesting.T) { 34 coretesting.MgoTestPackage(t) 35 } 36 37 type provisionerSuite struct { 38 testing.JujuConnSuite 39 40 machines []*state.Machine 41 42 authorizer apiservertesting.FakeAuthorizer 43 resources *common.Resources 44 provisioner *provisioner.ProvisionerAPI 45 } 46 47 var _ = gc.Suite(&provisionerSuite{}) 48 49 func (s *provisionerSuite) SetUpTest(c *gc.C) { 50 s.setUpTest(c, false) 51 } 52 53 func (s *provisionerSuite) setUpTest(c *gc.C, withStateServer bool) { 54 s.JujuConnSuite.SetUpTest(c) 55 56 // Reset previous machines (if any) and create 3 machines 57 // for the tests, plus an optional state server machine. 58 s.machines = nil 59 // Note that the specific machine ids allocated are assumed 60 // to be numerically consecutive from zero. 61 if withStateServer { 62 s.machines = append(s.machines, testing.AddStateServerMachine(c, s.State)) 63 } 64 for i := 0; i < 5; i++ { 65 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 66 c.Check(err, jc.ErrorIsNil) 67 s.machines = append(s.machines, machine) 68 } 69 70 // Create a FakeAuthorizer so we can check permissions, 71 // set up assuming we logged in as the environment manager. 72 s.authorizer = apiservertesting.FakeAuthorizer{ 73 EnvironManager: true, 74 } 75 76 // Create the resource registry separately to track invocations to 77 // Register, and to register the root for tools URLs. 78 s.resources = common.NewResources() 79 80 // Create a provisioner API for the machine. 81 provisionerAPI, err := provisioner.NewProvisionerAPI( 82 s.State, 83 s.resources, 84 s.authorizer, 85 ) 86 c.Assert(err, jc.ErrorIsNil) 87 s.provisioner = provisionerAPI 88 } 89 90 type withoutStateServerSuite struct { 91 provisionerSuite 92 *commontesting.EnvironWatcherTest 93 } 94 95 var _ = gc.Suite(&withoutStateServerSuite{}) 96 97 func (s *withoutStateServerSuite) SetUpTest(c *gc.C) { 98 s.setUpTest(c, false) 99 s.EnvironWatcherTest = commontesting.NewEnvironWatcherTest(s.provisioner, s.State, s.resources, commontesting.HasSecrets) 100 } 101 102 func (s *withoutStateServerSuite) TestProvisionerFailsWithNonMachineAgentNonManagerUser(c *gc.C) { 103 anAuthorizer := s.authorizer 104 anAuthorizer.EnvironManager = true 105 // Works with an environment manager, which is not a machine agent. 106 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 107 c.Assert(err, jc.ErrorIsNil) 108 c.Assert(aProvisioner, gc.NotNil) 109 110 // But fails with neither a machine agent or an environment manager. 111 anAuthorizer.EnvironManager = false 112 aProvisioner, err = provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 113 c.Assert(err, gc.NotNil) 114 c.Assert(aProvisioner, gc.IsNil) 115 c.Assert(err, gc.ErrorMatches, "permission denied") 116 } 117 118 func (s *withoutStateServerSuite) TestSetPasswords(c *gc.C) { 119 args := params.EntityPasswords{ 120 Changes: []params.EntityPassword{ 121 {Tag: s.machines[0].Tag().String(), Password: "xxx0-1234567890123457890"}, 122 {Tag: s.machines[1].Tag().String(), Password: "xxx1-1234567890123457890"}, 123 {Tag: s.machines[2].Tag().String(), Password: "xxx2-1234567890123457890"}, 124 {Tag: s.machines[3].Tag().String(), Password: "xxx3-1234567890123457890"}, 125 {Tag: s.machines[4].Tag().String(), Password: "xxx4-1234567890123457890"}, 126 {Tag: "machine-42", Password: "foo"}, 127 {Tag: "unit-foo-0", Password: "zzz"}, 128 {Tag: "service-bar", Password: "abc"}, 129 }, 130 } 131 results, err := s.provisioner.SetPasswords(args) 132 c.Assert(err, jc.ErrorIsNil) 133 c.Assert(results, gc.DeepEquals, params.ErrorResults{ 134 Results: []params.ErrorResult{ 135 {nil}, 136 {nil}, 137 {nil}, 138 {nil}, 139 {nil}, 140 {apiservertesting.NotFoundError("machine 42")}, 141 {apiservertesting.ErrUnauthorized}, 142 {apiservertesting.ErrUnauthorized}, 143 }, 144 }) 145 146 // Verify the changes to both machines succeeded. 147 for i, machine := range s.machines { 148 c.Logf("trying %q password", machine.Tag()) 149 err = machine.Refresh() 150 c.Assert(err, jc.ErrorIsNil) 151 changed := machine.PasswordValid(fmt.Sprintf("xxx%d-1234567890123457890", i)) 152 c.Assert(changed, jc.IsTrue) 153 } 154 } 155 156 func (s *withoutStateServerSuite) TestShortSetPasswords(c *gc.C) { 157 args := params.EntityPasswords{ 158 Changes: []params.EntityPassword{ 159 {Tag: s.machines[1].Tag().String(), Password: "xxx1"}, 160 }, 161 } 162 results, err := s.provisioner.SetPasswords(args) 163 c.Assert(err, jc.ErrorIsNil) 164 c.Assert(results.Results, gc.HasLen, 1) 165 c.Assert(results.Results[0].Error, gc.ErrorMatches, 166 "password is only 4 bytes long, and is not a valid Agent password") 167 } 168 169 func (s *withoutStateServerSuite) TestLifeAsMachineAgent(c *gc.C) { 170 // NOTE: This and the next call serve to test the two 171 // different authorization schemes: 172 // 1. Machine agents can access their own machine and 173 // any container that has their own machine as parent; 174 // 2. Environment managers can access any machine without 175 // a parent. 176 // There's no need to repeat this test for each method, 177 // because the authorization logic is common. 178 179 // Login as a machine agent for machine 0. 180 anAuthorizer := s.authorizer 181 anAuthorizer.EnvironManager = false 182 anAuthorizer.Tag = s.machines[0].Tag() 183 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 184 c.Assert(err, jc.ErrorIsNil) 185 c.Assert(aProvisioner, gc.NotNil) 186 187 // Make the machine dead before trying to add containers. 188 err = s.machines[0].EnsureDead() 189 c.Assert(err, jc.ErrorIsNil) 190 191 // Create some containers to work on. 192 template := state.MachineTemplate{ 193 Series: "quantal", 194 Jobs: []state.MachineJob{state.JobHostUnits}, 195 } 196 var containers []*state.Machine 197 for i := 0; i < 3; i++ { 198 container, err := s.State.AddMachineInsideMachine(template, s.machines[0].Id(), instance.LXC) 199 c.Check(err, jc.ErrorIsNil) 200 containers = append(containers, container) 201 } 202 // Make one container dead. 203 err = containers[1].EnsureDead() 204 c.Assert(err, jc.ErrorIsNil) 205 206 args := params.Entities{Entities: []params.Entity{ 207 {Tag: s.machines[0].Tag().String()}, 208 {Tag: s.machines[1].Tag().String()}, 209 {Tag: containers[0].Tag().String()}, 210 {Tag: containers[1].Tag().String()}, 211 {Tag: containers[2].Tag().String()}, 212 {Tag: "machine-42"}, 213 {Tag: "unit-foo-0"}, 214 {Tag: "service-bar"}, 215 }} 216 result, err := aProvisioner.Life(args) 217 c.Assert(err, jc.ErrorIsNil) 218 c.Assert(result, gc.DeepEquals, params.LifeResults{ 219 Results: []params.LifeResult{ 220 {Life: "dead"}, 221 {Error: apiservertesting.ErrUnauthorized}, 222 {Life: "alive"}, 223 {Life: "dead"}, 224 {Life: "alive"}, 225 {Error: apiservertesting.ErrUnauthorized}, 226 {Error: apiservertesting.ErrUnauthorized}, 227 {Error: apiservertesting.ErrUnauthorized}, 228 }, 229 }) 230 } 231 232 func (s *withoutStateServerSuite) TestLifeAsEnvironManager(c *gc.C) { 233 err := s.machines[1].EnsureDead() 234 c.Assert(err, jc.ErrorIsNil) 235 err = s.machines[1].Refresh() 236 c.Assert(err, jc.ErrorIsNil) 237 c.Assert(s.machines[0].Life(), gc.Equals, state.Alive) 238 c.Assert(s.machines[1].Life(), gc.Equals, state.Dead) 239 c.Assert(s.machines[2].Life(), gc.Equals, state.Alive) 240 241 args := params.Entities{Entities: []params.Entity{ 242 {Tag: s.machines[0].Tag().String()}, 243 {Tag: s.machines[1].Tag().String()}, 244 {Tag: s.machines[2].Tag().String()}, 245 {Tag: "machine-42"}, 246 {Tag: "unit-foo-0"}, 247 {Tag: "service-bar"}, 248 }} 249 result, err := s.provisioner.Life(args) 250 c.Assert(err, jc.ErrorIsNil) 251 c.Assert(result, gc.DeepEquals, params.LifeResults{ 252 Results: []params.LifeResult{ 253 {Life: "alive"}, 254 {Life: "dead"}, 255 {Life: "alive"}, 256 {Error: apiservertesting.NotFoundError("machine 42")}, 257 {Error: apiservertesting.ErrUnauthorized}, 258 {Error: apiservertesting.ErrUnauthorized}, 259 }, 260 }) 261 262 // Remove the subordinate and make sure it's detected. 263 err = s.machines[1].Remove() 264 c.Assert(err, jc.ErrorIsNil) 265 err = s.machines[1].Refresh() 266 c.Assert(err, jc.Satisfies, errors.IsNotFound) 267 268 result, err = s.provisioner.Life(params.Entities{ 269 Entities: []params.Entity{ 270 {Tag: s.machines[1].Tag().String()}, 271 }, 272 }) 273 c.Assert(err, jc.ErrorIsNil) 274 c.Assert(result, gc.DeepEquals, params.LifeResults{ 275 Results: []params.LifeResult{ 276 {Error: apiservertesting.NotFoundError("machine 1")}, 277 }, 278 }) 279 } 280 281 func (s *withoutStateServerSuite) TestRemove(c *gc.C) { 282 err := s.machines[1].EnsureDead() 283 c.Assert(err, jc.ErrorIsNil) 284 s.assertLife(c, 0, state.Alive) 285 s.assertLife(c, 1, state.Dead) 286 s.assertLife(c, 2, state.Alive) 287 288 args := params.Entities{Entities: []params.Entity{ 289 {Tag: s.machines[0].Tag().String()}, 290 {Tag: s.machines[1].Tag().String()}, 291 {Tag: s.machines[2].Tag().String()}, 292 {Tag: "machine-42"}, 293 {Tag: "unit-foo-0"}, 294 {Tag: "service-bar"}, 295 }} 296 result, err := s.provisioner.Remove(args) 297 c.Assert(err, jc.ErrorIsNil) 298 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 299 Results: []params.ErrorResult{ 300 {¶ms.Error{Message: `cannot remove entity "machine-0": still alive`}}, 301 {nil}, 302 {¶ms.Error{Message: `cannot remove entity "machine-2": still alive`}}, 303 {apiservertesting.NotFoundError("machine 42")}, 304 {apiservertesting.ErrUnauthorized}, 305 {apiservertesting.ErrUnauthorized}, 306 }, 307 }) 308 309 // Verify the changes. 310 s.assertLife(c, 0, state.Alive) 311 err = s.machines[2].Refresh() 312 c.Assert(err, jc.ErrorIsNil) 313 s.assertLife(c, 2, state.Alive) 314 } 315 316 func (s *withoutStateServerSuite) TestSetStatus(c *gc.C) { 317 err := s.machines[0].SetStatus(state.StatusStarted, "blah", nil) 318 c.Assert(err, jc.ErrorIsNil) 319 err = s.machines[1].SetStatus(state.StatusStopped, "foo", nil) 320 c.Assert(err, jc.ErrorIsNil) 321 err = s.machines[2].SetStatus(state.StatusError, "not really", nil) 322 c.Assert(err, jc.ErrorIsNil) 323 324 args := params.SetStatus{ 325 Entities: []params.EntityStatus{ 326 {Tag: s.machines[0].Tag().String(), Status: params.StatusError, Info: "not really", 327 Data: map[string]interface{}{"foo": "bar"}}, 328 {Tag: s.machines[1].Tag().String(), Status: params.StatusStopped, Info: "foobar"}, 329 {Tag: s.machines[2].Tag().String(), Status: params.StatusStarted, Info: "again"}, 330 {Tag: "machine-42", Status: params.StatusStarted, Info: "blah"}, 331 {Tag: "unit-foo-0", Status: params.StatusStopped, Info: "foobar"}, 332 {Tag: "service-bar", Status: params.StatusStopped, Info: "foobar"}, 333 }} 334 result, err := s.provisioner.SetStatus(args) 335 c.Assert(err, jc.ErrorIsNil) 336 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 337 Results: []params.ErrorResult{ 338 {nil}, 339 {nil}, 340 {nil}, 341 {apiservertesting.NotFoundError("machine 42")}, 342 {apiservertesting.ErrUnauthorized}, 343 {apiservertesting.ErrUnauthorized}, 344 }, 345 }) 346 347 // Verify the changes. 348 s.assertStatus(c, 0, state.StatusError, "not really", map[string]interface{}{"foo": "bar"}) 349 s.assertStatus(c, 1, state.StatusStopped, "foobar", map[string]interface{}{}) 350 s.assertStatus(c, 2, state.StatusStarted, "again", map[string]interface{}{}) 351 } 352 353 func (s *withoutStateServerSuite) TestMachinesWithTransientErrors(c *gc.C) { 354 err := s.machines[0].SetStatus(state.StatusStarted, "blah", nil) 355 c.Assert(err, jc.ErrorIsNil) 356 err = s.machines[1].SetStatus(state.StatusError, "transient error", 357 map[string]interface{}{"transient": true, "foo": "bar"}) 358 c.Assert(err, jc.ErrorIsNil) 359 err = s.machines[2].SetStatus(state.StatusError, "error", map[string]interface{}{"transient": false}) 360 c.Assert(err, jc.ErrorIsNil) 361 err = s.machines[3].SetStatus(state.StatusError, "error", nil) 362 c.Assert(err, jc.ErrorIsNil) 363 // Machine 4 is provisioned but error not reset yet. 364 err = s.machines[4].SetStatus(state.StatusError, "transient error", 365 map[string]interface{}{"transient": true, "foo": "bar"}) 366 c.Assert(err, jc.ErrorIsNil) 367 hwChars := instance.MustParseHardware("arch=i386", "mem=4G") 368 err = s.machines[4].SetProvisioned("i-am", "fake_nonce", &hwChars) 369 c.Assert(err, jc.ErrorIsNil) 370 371 result, err := s.provisioner.MachinesWithTransientErrors() 372 c.Assert(err, jc.ErrorIsNil) 373 c.Assert(result, gc.DeepEquals, params.StatusResults{ 374 Results: []params.StatusResult{ 375 {Id: "1", Life: "alive", Status: "error", Info: "transient error", 376 Data: map[string]interface{}{"transient": true, "foo": "bar"}}, 377 }, 378 }) 379 } 380 381 func (s *withoutStateServerSuite) TestMachinesWithTransientErrorsPermission(c *gc.C) { 382 // Machines where there's permission issues are omitted. 383 anAuthorizer := s.authorizer 384 anAuthorizer.EnvironManager = false 385 anAuthorizer.Tag = names.NewMachineTag("1") 386 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, 387 anAuthorizer) 388 err = s.machines[0].SetStatus(state.StatusStarted, "blah", nil) 389 c.Assert(err, jc.ErrorIsNil) 390 err = s.machines[1].SetStatus(state.StatusError, "transient error", 391 map[string]interface{}{"transient": true, "foo": "bar"}) 392 c.Assert(err, jc.ErrorIsNil) 393 err = s.machines[2].SetStatus(state.StatusError, "error", map[string]interface{}{"transient": false}) 394 c.Assert(err, jc.ErrorIsNil) 395 err = s.machines[3].SetStatus(state.StatusError, "error", nil) 396 c.Assert(err, jc.ErrorIsNil) 397 398 result, err := aProvisioner.MachinesWithTransientErrors() 399 c.Assert(err, jc.ErrorIsNil) 400 c.Assert(result, gc.DeepEquals, params.StatusResults{ 401 Results: []params.StatusResult{ 402 {Id: "1", Life: "alive", Status: "error", Info: "transient error", 403 Data: map[string]interface{}{"transient": true, "foo": "bar"}}, 404 }, 405 }) 406 } 407 408 func (s *withoutStateServerSuite) TestEnsureDead(c *gc.C) { 409 err := s.machines[1].EnsureDead() 410 c.Assert(err, jc.ErrorIsNil) 411 s.assertLife(c, 0, state.Alive) 412 s.assertLife(c, 1, state.Dead) 413 s.assertLife(c, 2, state.Alive) 414 415 args := params.Entities{Entities: []params.Entity{ 416 {Tag: s.machines[0].Tag().String()}, 417 {Tag: s.machines[1].Tag().String()}, 418 {Tag: s.machines[2].Tag().String()}, 419 {Tag: "machine-42"}, 420 {Tag: "unit-foo-0"}, 421 {Tag: "service-bar"}, 422 }} 423 result, err := s.provisioner.EnsureDead(args) 424 c.Assert(err, jc.ErrorIsNil) 425 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 426 Results: []params.ErrorResult{ 427 {nil}, 428 {nil}, 429 {nil}, 430 {apiservertesting.NotFoundError("machine 42")}, 431 {apiservertesting.ErrUnauthorized}, 432 {apiservertesting.ErrUnauthorized}, 433 }, 434 }) 435 436 // Verify the changes. 437 s.assertLife(c, 0, state.Dead) 438 s.assertLife(c, 1, state.Dead) 439 s.assertLife(c, 2, state.Dead) 440 } 441 442 func (s *withoutStateServerSuite) assertLife(c *gc.C, index int, expectLife state.Life) { 443 err := s.machines[index].Refresh() 444 c.Assert(err, jc.ErrorIsNil) 445 c.Assert(s.machines[index].Life(), gc.Equals, expectLife) 446 } 447 448 func (s *withoutStateServerSuite) assertStatus(c *gc.C, index int, expectStatus state.Status, expectInfo string, 449 expectData map[string]interface{}) { 450 451 status, info, data, err := s.machines[index].Status() 452 c.Assert(err, jc.ErrorIsNil) 453 c.Assert(status, gc.Equals, expectStatus) 454 c.Assert(info, gc.Equals, expectInfo) 455 c.Assert(data, gc.DeepEquals, expectData) 456 } 457 458 func (s *withoutStateServerSuite) TestWatchContainers(c *gc.C) { 459 c.Assert(s.resources.Count(), gc.Equals, 0) 460 461 args := params.WatchContainers{Params: []params.WatchContainer{ 462 {MachineTag: s.machines[0].Tag().String(), ContainerType: string(instance.LXC)}, 463 {MachineTag: s.machines[1].Tag().String(), ContainerType: string(instance.KVM)}, 464 {MachineTag: "machine-42", ContainerType: ""}, 465 {MachineTag: "unit-foo-0", ContainerType: ""}, 466 {MachineTag: "service-bar", ContainerType: ""}, 467 }} 468 result, err := s.provisioner.WatchContainers(args) 469 c.Assert(err, jc.ErrorIsNil) 470 c.Assert(result, gc.DeepEquals, params.StringsWatchResults{ 471 Results: []params.StringsWatchResult{ 472 {StringsWatcherId: "1", Changes: []string{}}, 473 {StringsWatcherId: "2", Changes: []string{}}, 474 {Error: apiservertesting.NotFoundError("machine 42")}, 475 {Error: apiservertesting.ErrUnauthorized}, 476 {Error: apiservertesting.ErrUnauthorized}, 477 }, 478 }) 479 480 // Verify the resources were registered and stop them when done. 481 c.Assert(s.resources.Count(), gc.Equals, 2) 482 m0Watcher := s.resources.Get("1") 483 defer statetesting.AssertStop(c, m0Watcher) 484 m1Watcher := s.resources.Get("2") 485 defer statetesting.AssertStop(c, m1Watcher) 486 487 // Check that the Watch has consumed the initial event ("returned" 488 // in the Watch call) 489 wc0 := statetesting.NewStringsWatcherC(c, s.State, m0Watcher.(state.StringsWatcher)) 490 wc0.AssertNoChange() 491 wc1 := statetesting.NewStringsWatcherC(c, s.State, m1Watcher.(state.StringsWatcher)) 492 wc1.AssertNoChange() 493 } 494 495 func (s *withoutStateServerSuite) TestWatchAllContainers(c *gc.C) { 496 c.Assert(s.resources.Count(), gc.Equals, 0) 497 498 args := params.WatchContainers{Params: []params.WatchContainer{ 499 {MachineTag: s.machines[0].Tag().String()}, 500 {MachineTag: s.machines[1].Tag().String()}, 501 {MachineTag: "machine-42"}, 502 {MachineTag: "unit-foo-0"}, 503 {MachineTag: "service-bar"}, 504 }} 505 result, err := s.provisioner.WatchAllContainers(args) 506 c.Assert(err, jc.ErrorIsNil) 507 c.Assert(result, gc.DeepEquals, params.StringsWatchResults{ 508 Results: []params.StringsWatchResult{ 509 {StringsWatcherId: "1", Changes: []string{}}, 510 {StringsWatcherId: "2", Changes: []string{}}, 511 {Error: apiservertesting.NotFoundError("machine 42")}, 512 {Error: apiservertesting.ErrUnauthorized}, 513 {Error: apiservertesting.ErrUnauthorized}, 514 }, 515 }) 516 517 // Verify the resources were registered and stop them when done. 518 c.Assert(s.resources.Count(), gc.Equals, 2) 519 m0Watcher := s.resources.Get("1") 520 defer statetesting.AssertStop(c, m0Watcher) 521 m1Watcher := s.resources.Get("2") 522 defer statetesting.AssertStop(c, m1Watcher) 523 524 // Check that the Watch has consumed the initial event ("returned" 525 // in the Watch call) 526 wc0 := statetesting.NewStringsWatcherC(c, s.State, m0Watcher.(state.StringsWatcher)) 527 wc0.AssertNoChange() 528 wc1 := statetesting.NewStringsWatcherC(c, s.State, m1Watcher.(state.StringsWatcher)) 529 wc1.AssertNoChange() 530 } 531 532 func (s *withoutStateServerSuite) TestEnvironConfigNonManager(c *gc.C) { 533 // Now test it with a non-environment manager and make sure 534 // the secret attributes are masked. 535 anAuthorizer := s.authorizer 536 anAuthorizer.Tag = names.NewMachineTag("1") 537 anAuthorizer.EnvironManager = false 538 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, 539 anAuthorizer) 540 c.Assert(err, jc.ErrorIsNil) 541 s.AssertEnvironConfig(c, aProvisioner, commontesting.NoSecrets) 542 } 543 544 func (s *withoutStateServerSuite) TestStatus(c *gc.C) { 545 err := s.machines[0].SetStatus(state.StatusStarted, "blah", nil) 546 c.Assert(err, jc.ErrorIsNil) 547 err = s.machines[1].SetStatus(state.StatusStopped, "foo", nil) 548 c.Assert(err, jc.ErrorIsNil) 549 err = s.machines[2].SetStatus(state.StatusError, "not really", map[string]interface{}{"foo": "bar"}) 550 c.Assert(err, jc.ErrorIsNil) 551 552 args := params.Entities{Entities: []params.Entity{ 553 {Tag: s.machines[0].Tag().String()}, 554 {Tag: s.machines[1].Tag().String()}, 555 {Tag: s.machines[2].Tag().String()}, 556 {Tag: "machine-42"}, 557 {Tag: "unit-foo-0"}, 558 {Tag: "service-bar"}, 559 }} 560 result, err := s.provisioner.Status(args) 561 c.Assert(err, jc.ErrorIsNil) 562 c.Assert(result, gc.DeepEquals, params.StatusResults{ 563 Results: []params.StatusResult{ 564 {Status: params.StatusStarted, Info: "blah", Data: map[string]interface{}{}}, 565 {Status: params.StatusStopped, Info: "foo", Data: map[string]interface{}{}}, 566 {Status: params.StatusError, Info: "not really", Data: map[string]interface{}{"foo": "bar"}}, 567 {Error: apiservertesting.NotFoundError("machine 42")}, 568 {Error: apiservertesting.ErrUnauthorized}, 569 {Error: apiservertesting.ErrUnauthorized}, 570 }, 571 }) 572 } 573 574 func (s *withoutStateServerSuite) TestSeries(c *gc.C) { 575 // Add a machine with different series. 576 foobarMachine, err := s.State.AddMachine("foobar", state.JobHostUnits) 577 c.Assert(err, jc.ErrorIsNil) 578 579 args := params.Entities{Entities: []params.Entity{ 580 {Tag: s.machines[0].Tag().String()}, 581 {Tag: foobarMachine.Tag().String()}, 582 {Tag: s.machines[2].Tag().String()}, 583 {Tag: "machine-42"}, 584 {Tag: "unit-foo-0"}, 585 {Tag: "service-bar"}, 586 }} 587 result, err := s.provisioner.Series(args) 588 c.Assert(err, jc.ErrorIsNil) 589 c.Assert(result, gc.DeepEquals, params.StringResults{ 590 Results: []params.StringResult{ 591 {Result: s.machines[0].Series()}, 592 {Result: foobarMachine.Series()}, 593 {Result: s.machines[2].Series()}, 594 {Error: apiservertesting.NotFoundError("machine 42")}, 595 {Error: apiservertesting.ErrUnauthorized}, 596 {Error: apiservertesting.ErrUnauthorized}, 597 }, 598 }) 599 } 600 601 func (s *withoutStateServerSuite) TestDistributionGroup(c *gc.C) { 602 addUnits := func(name string, machines ...*state.Machine) (units []*state.Unit) { 603 svc := s.AddTestingService(c, name, s.AddTestingCharm(c, name)) 604 for _, m := range machines { 605 unit, err := svc.AddUnit() 606 c.Assert(err, jc.ErrorIsNil) 607 err = unit.AssignToMachine(m) 608 c.Assert(err, jc.ErrorIsNil) 609 units = append(units, unit) 610 } 611 return units 612 } 613 setProvisioned := func(id string) { 614 m, err := s.State.Machine(id) 615 c.Assert(err, jc.ErrorIsNil) 616 err = m.SetProvisioned(instance.Id("machine-"+id+"-inst"), "nonce", nil) 617 c.Assert(err, jc.ErrorIsNil) 618 } 619 620 mysqlUnit := addUnits("mysql", s.machines[0], s.machines[3])[0] 621 wordpressUnits := addUnits("wordpress", s.machines[0], s.machines[1], s.machines[2]) 622 623 // Unassign wordpress/1 from machine-1. 624 // The unit should not show up in the results. 625 err := wordpressUnits[1].UnassignFromMachine() 626 c.Assert(err, jc.ErrorIsNil) 627 628 // Provision machines 1, 2 and 3. Machine-0 remains 629 // unprovisioned, and machine-1 has no units, and so 630 // neither will show up in the results. 631 setProvisioned("1") 632 setProvisioned("2") 633 setProvisioned("3") 634 635 // Add a few state servers, provision two of them. 636 _, err = s.State.EnsureAvailability(3, constraints.Value{}, "quantal", nil) 637 c.Assert(err, jc.ErrorIsNil) 638 setProvisioned("5") 639 setProvisioned("7") 640 641 // Create a logging service, subordinate to mysql. 642 s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging")) 643 eps, err := s.State.InferEndpoints("mysql", "logging") 644 c.Assert(err, jc.ErrorIsNil) 645 rel, err := s.State.AddRelation(eps...) 646 c.Assert(err, jc.ErrorIsNil) 647 ru, err := rel.Unit(mysqlUnit) 648 c.Assert(err, jc.ErrorIsNil) 649 err = ru.EnterScope(nil) 650 c.Assert(err, jc.ErrorIsNil) 651 652 args := params.Entities{Entities: []params.Entity{ 653 {Tag: s.machines[0].Tag().String()}, 654 {Tag: s.machines[1].Tag().String()}, 655 {Tag: s.machines[2].Tag().String()}, 656 {Tag: s.machines[3].Tag().String()}, 657 {Tag: "machine-5"}, 658 }} 659 result, err := s.provisioner.DistributionGroup(args) 660 c.Assert(err, jc.ErrorIsNil) 661 c.Assert(result, gc.DeepEquals, params.DistributionGroupResults{ 662 Results: []params.DistributionGroupResult{ 663 {Result: []instance.Id{"machine-2-inst", "machine-3-inst"}}, 664 {Result: []instance.Id{}}, 665 {Result: []instance.Id{"machine-2-inst"}}, 666 {Result: []instance.Id{"machine-3-inst"}}, 667 {Result: []instance.Id{"machine-5-inst", "machine-7-inst"}}, 668 }, 669 }) 670 } 671 672 func (s *withoutStateServerSuite) TestDistributionGroupEnvironManagerAuth(c *gc.C) { 673 args := params.Entities{Entities: []params.Entity{ 674 {Tag: "machine-0"}, 675 {Tag: "machine-42"}, 676 {Tag: "machine-0-lxc-99"}, 677 {Tag: "unit-foo-0"}, 678 {Tag: "service-bar"}, 679 }} 680 result, err := s.provisioner.DistributionGroup(args) 681 c.Assert(err, jc.ErrorIsNil) 682 c.Assert(result, gc.DeepEquals, params.DistributionGroupResults{ 683 Results: []params.DistributionGroupResult{ 684 // environ manager may access any top-level machines. 685 {Result: []instance.Id{}}, 686 {Error: apiservertesting.NotFoundError("machine 42")}, 687 // only a machine agent for the container or its 688 // parent may access it. 689 {Error: apiservertesting.ErrUnauthorized}, 690 // non-machines always unauthorized 691 {Error: apiservertesting.ErrUnauthorized}, 692 {Error: apiservertesting.ErrUnauthorized}, 693 }, 694 }) 695 } 696 697 func (s *withoutStateServerSuite) TestDistributionGroupMachineAgentAuth(c *gc.C) { 698 anAuthorizer := s.authorizer 699 anAuthorizer.Tag = names.NewMachineTag("1") 700 anAuthorizer.EnvironManager = false 701 provisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 702 c.Check(err, jc.ErrorIsNil) 703 args := params.Entities{Entities: []params.Entity{ 704 {Tag: "machine-0"}, 705 {Tag: "machine-1"}, 706 {Tag: "machine-42"}, 707 {Tag: "machine-0-lxc-99"}, 708 {Tag: "machine-1-lxc-99"}, 709 {Tag: "machine-1-lxc-99-lxc-100"}, 710 }} 711 result, err := provisioner.DistributionGroup(args) 712 c.Assert(err, jc.ErrorIsNil) 713 c.Assert(result, gc.DeepEquals, params.DistributionGroupResults{ 714 Results: []params.DistributionGroupResult{ 715 {Error: apiservertesting.ErrUnauthorized}, 716 {Result: []instance.Id{}}, 717 {Error: apiservertesting.ErrUnauthorized}, 718 // only a machine agent for the container or its 719 // parent may access it. 720 {Error: apiservertesting.ErrUnauthorized}, 721 {Error: apiservertesting.NotFoundError("machine 1/lxc/99")}, 722 {Error: apiservertesting.ErrUnauthorized}, 723 }, 724 }) 725 } 726 727 func (s *withoutStateServerSuite) TestProvisioningInfo(c *gc.C) { 728 cons := constraints.MustParse("cpu-cores=123 mem=8G networks=^net3,^net4") 729 template := state.MachineTemplate{ 730 Series: "quantal", 731 Jobs: []state.MachineJob{state.JobHostUnits}, 732 Constraints: cons, 733 Placement: "valid", 734 RequestedNetworks: []string{"net1", "net2"}, 735 BlockDevices: []state.BlockDeviceParams{{Size: 1000}, {Size: 2000}}, 736 } 737 placementMachine, err := s.State.AddOneMachine(template) 738 c.Assert(err, jc.ErrorIsNil) 739 740 args := params.Entities{Entities: []params.Entity{ 741 {Tag: s.machines[0].Tag().String()}, 742 {Tag: placementMachine.Tag().String()}, 743 {Tag: "machine-42"}, 744 {Tag: "unit-foo-0"}, 745 {Tag: "service-bar"}, 746 }} 747 result, err := s.provisioner.ProvisioningInfo(args) 748 c.Assert(err, jc.ErrorIsNil) 749 c.Assert(result, gc.DeepEquals, params.ProvisioningInfoResults{ 750 Results: []params.ProvisioningInfoResult{ 751 {Result: ¶ms.ProvisioningInfo{ 752 Series: "quantal", 753 Networks: []string{}, 754 Jobs: []multiwatcher.MachineJob{multiwatcher.JobHostUnits}, 755 }}, 756 {Result: ¶ms.ProvisioningInfo{ 757 Series: "quantal", 758 Constraints: template.Constraints, 759 Placement: template.Placement, 760 Networks: template.RequestedNetworks, 761 Jobs: []multiwatcher.MachineJob{multiwatcher.JobHostUnits}, 762 Volumes: []storage.VolumeParams{{Name: "0", Size: 1000}, {Name: "1", Size: 2000}}, 763 }}, 764 {Error: apiservertesting.NotFoundError("machine 42")}, 765 {Error: apiservertesting.ErrUnauthorized}, 766 {Error: apiservertesting.ErrUnauthorized}, 767 }, 768 }) 769 } 770 771 func (s *withoutStateServerSuite) TestProvisioningInfoPermissions(c *gc.C) { 772 // Login as a machine agent for machine 0. 773 anAuthorizer := s.authorizer 774 anAuthorizer.EnvironManager = false 775 anAuthorizer.Tag = s.machines[0].Tag() 776 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 777 c.Assert(err, jc.ErrorIsNil) 778 c.Assert(aProvisioner, gc.NotNil) 779 780 args := params.Entities{Entities: []params.Entity{ 781 {Tag: s.machines[0].Tag().String()}, 782 {Tag: s.machines[0].Tag().String() + "-lxc-0"}, 783 {Tag: "machine-42"}, 784 {Tag: s.machines[1].Tag().String()}, 785 {Tag: "service-bar"}, 786 }} 787 788 // Only machine 0 and containers therein can be accessed. 789 results, err := aProvisioner.ProvisioningInfo(args) 790 c.Assert(results, gc.DeepEquals, params.ProvisioningInfoResults{ 791 Results: []params.ProvisioningInfoResult{ 792 {Result: ¶ms.ProvisioningInfo{ 793 Series: "quantal", 794 Networks: []string{}, 795 Jobs: []multiwatcher.MachineJob{multiwatcher.JobHostUnits}, 796 }}, 797 {Error: apiservertesting.NotFoundError("machine 0/lxc/0")}, 798 {Error: apiservertesting.ErrUnauthorized}, 799 {Error: apiservertesting.ErrUnauthorized}, 800 {Error: apiservertesting.ErrUnauthorized}, 801 }, 802 }) 803 } 804 805 func (s *withoutStateServerSuite) TestConstraints(c *gc.C) { 806 // Add a machine with some constraints. 807 cons := constraints.MustParse("cpu-cores=123", "mem=8G", "networks=net3,^net4") 808 template := state.MachineTemplate{ 809 Series: "quantal", 810 Jobs: []state.MachineJob{state.JobHostUnits}, 811 Constraints: cons, 812 } 813 consMachine, err := s.State.AddOneMachine(template) 814 c.Assert(err, jc.ErrorIsNil) 815 816 machine0Constraints, err := s.machines[0].Constraints() 817 c.Assert(err, jc.ErrorIsNil) 818 819 args := params.Entities{Entities: []params.Entity{ 820 {Tag: s.machines[0].Tag().String()}, 821 {Tag: consMachine.Tag().String()}, 822 {Tag: "machine-42"}, 823 {Tag: "unit-foo-0"}, 824 {Tag: "service-bar"}, 825 }} 826 result, err := s.provisioner.Constraints(args) 827 c.Assert(err, jc.ErrorIsNil) 828 c.Assert(result, gc.DeepEquals, params.ConstraintsResults{ 829 Results: []params.ConstraintsResult{ 830 {Constraints: machine0Constraints}, 831 {Constraints: template.Constraints}, 832 {Error: apiservertesting.NotFoundError("machine 42")}, 833 {Error: apiservertesting.ErrUnauthorized}, 834 {Error: apiservertesting.ErrUnauthorized}, 835 }, 836 }) 837 } 838 839 func (s *withoutStateServerSuite) TestRequestedNetworks(c *gc.C) { 840 // Add a machine with some requested networks. 841 template := state.MachineTemplate{ 842 Series: "quantal", 843 Jobs: []state.MachineJob{state.JobHostUnits}, 844 RequestedNetworks: []string{"net1", "net2"}, 845 } 846 netsMachine, err := s.State.AddOneMachine(template) 847 c.Assert(err, jc.ErrorIsNil) 848 849 networksMachine0, err := s.machines[0].RequestedNetworks() 850 c.Assert(err, jc.ErrorIsNil) 851 852 args := params.Entities{Entities: []params.Entity{ 853 {Tag: s.machines[0].Tag().String()}, 854 {Tag: netsMachine.Tag().String()}, 855 {Tag: "machine-42"}, 856 {Tag: "unit-foo-0"}, 857 {Tag: "service-bar"}, 858 }} 859 result, err := s.provisioner.RequestedNetworks(args) 860 c.Assert(err, jc.ErrorIsNil) 861 c.Assert(result, gc.DeepEquals, params.RequestedNetworksResults{ 862 Results: []params.RequestedNetworkResult{ 863 { 864 Networks: networksMachine0, 865 }, 866 { 867 Networks: template.RequestedNetworks, 868 }, 869 {Error: apiservertesting.NotFoundError("machine 42")}, 870 {Error: apiservertesting.ErrUnauthorized}, 871 {Error: apiservertesting.ErrUnauthorized}, 872 }, 873 }) 874 } 875 876 func (s *withoutStateServerSuite) TestSetProvisioned(c *gc.C) { 877 // Provision machine 0 first. 878 hwChars := instance.MustParseHardware("arch=i386", "mem=4G") 879 err := s.machines[0].SetProvisioned("i-am", "fake_nonce", &hwChars) 880 c.Assert(err, jc.ErrorIsNil) 881 882 args := params.SetProvisioned{Machines: []params.MachineSetProvisioned{ 883 {Tag: s.machines[0].Tag().String(), InstanceId: "i-was", Nonce: "fake_nonce", Characteristics: nil}, 884 {Tag: s.machines[1].Tag().String(), InstanceId: "i-will", Nonce: "fake_nonce", Characteristics: &hwChars}, 885 {Tag: s.machines[2].Tag().String(), InstanceId: "i-am-too", Nonce: "fake", Characteristics: nil}, 886 {Tag: "machine-42", InstanceId: "", Nonce: "", Characteristics: nil}, 887 {Tag: "unit-foo-0", InstanceId: "", Nonce: "", Characteristics: nil}, 888 {Tag: "service-bar", InstanceId: "", Nonce: "", Characteristics: nil}, 889 }} 890 result, err := s.provisioner.SetProvisioned(args) 891 c.Assert(err, jc.ErrorIsNil) 892 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 893 Results: []params.ErrorResult{ 894 {¶ms.Error{ 895 Message: `cannot set instance data for machine "0": already set`, 896 }}, 897 {nil}, 898 {nil}, 899 {apiservertesting.NotFoundError("machine 42")}, 900 {apiservertesting.ErrUnauthorized}, 901 {apiservertesting.ErrUnauthorized}, 902 }, 903 }) 904 905 // Verify machine 1 and 2 were provisioned. 906 c.Assert(s.machines[1].Refresh(), gc.IsNil) 907 c.Assert(s.machines[2].Refresh(), gc.IsNil) 908 909 instanceId, err := s.machines[1].InstanceId() 910 c.Assert(err, jc.ErrorIsNil) 911 c.Check(instanceId, gc.Equals, instance.Id("i-will")) 912 instanceId, err = s.machines[2].InstanceId() 913 c.Assert(err, jc.ErrorIsNil) 914 c.Check(instanceId, gc.Equals, instance.Id("i-am-too")) 915 c.Check(s.machines[1].CheckProvisioned("fake_nonce"), jc.IsTrue) 916 c.Check(s.machines[2].CheckProvisioned("fake"), jc.IsTrue) 917 gotHardware, err := s.machines[1].HardwareCharacteristics() 918 c.Assert(err, jc.ErrorIsNil) 919 c.Check(gotHardware, gc.DeepEquals, &hwChars) 920 } 921 922 func (s *withoutStateServerSuite) TestSetInstanceInfo(c *gc.C) { 923 // Provision machine 0 first. 924 hwChars := instance.MustParseHardware("arch=i386", "mem=4G") 925 err := s.machines[0].SetInstanceInfo("i-am", "fake_nonce", &hwChars, nil, nil, nil) 926 c.Assert(err, jc.ErrorIsNil) 927 928 volumesMachine, err := s.State.AddOneMachine(state.MachineTemplate{ 929 Series: "quantal", 930 Jobs: []state.MachineJob{state.JobHostUnits}, 931 BlockDevices: []state.BlockDeviceParams{{Size: 1000}}, 932 }) 933 934 networks := []params.Network{{ 935 Tag: "network-net1", 936 ProviderId: "net1", 937 CIDR: "0.1.2.0/24", 938 VLANTag: 0, 939 }, { 940 Tag: "network-vlan42", 941 ProviderId: "vlan42", 942 CIDR: "0.2.2.0/24", 943 VLANTag: 42, 944 }, { 945 Tag: "network-vlan69", 946 ProviderId: "vlan69", 947 CIDR: "0.3.2.0/24", 948 VLANTag: 69, 949 }, { 950 Tag: "network-vlan42", // duplicated; ignored 951 ProviderId: "vlan42", 952 CIDR: "0.2.2.0/24", 953 VLANTag: 42, 954 }} 955 ifaces := []params.NetworkInterface{{ 956 MACAddress: "aa:bb:cc:dd:ee:f0", 957 NetworkTag: "network-net1", 958 InterfaceName: "eth0", 959 IsVirtual: false, 960 }, { 961 MACAddress: "aa:bb:cc:dd:ee:f1", 962 NetworkTag: "network-net1", 963 InterfaceName: "eth1", 964 IsVirtual: false, 965 }, { 966 MACAddress: "aa:bb:cc:dd:ee:f1", 967 NetworkTag: "network-vlan42", 968 InterfaceName: "eth1.42", 969 IsVirtual: true, 970 }, { 971 MACAddress: "aa:bb:cc:dd:ee:f0", 972 NetworkTag: "network-vlan69", 973 InterfaceName: "eth0.69", 974 IsVirtual: true, 975 Disabled: true, 976 }, { 977 MACAddress: "aa:bb:cc:dd:ee:f1", // duplicated mac+net; ignored 978 NetworkTag: "network-vlan42", 979 InterfaceName: "eth2", 980 IsVirtual: true, 981 }, { 982 MACAddress: "aa:bb:cc:dd:ee:f2", 983 NetworkTag: "network-net1", 984 InterfaceName: "eth1", // duplicated name+machine id; ignored for machine 1. 985 IsVirtual: false, 986 }} 987 args := params.InstancesInfo{Machines: []params.InstanceInfo{{ 988 Tag: s.machines[0].Tag().String(), 989 InstanceId: "i-was", 990 Nonce: "fake_nonce", 991 }, { 992 Tag: s.machines[1].Tag().String(), 993 InstanceId: "i-will", 994 Nonce: "fake_nonce", 995 Characteristics: &hwChars, 996 Networks: networks, 997 Interfaces: ifaces, 998 }, { 999 Tag: s.machines[2].Tag().String(), 1000 InstanceId: "i-am-too", 1001 Nonce: "fake", 1002 Characteristics: nil, 1003 Networks: networks, 1004 Interfaces: ifaces, 1005 }, { 1006 Tag: volumesMachine.Tag().String(), 1007 InstanceId: "i-am-also", 1008 Nonce: "fake", 1009 Volumes: []storage.BlockDevice{{Name: "0", Size: 1234}}, 1010 }, 1011 {Tag: "machine-42"}, 1012 {Tag: "unit-foo-0"}, 1013 {Tag: "service-bar"}, 1014 }} 1015 result, err := s.provisioner.SetInstanceInfo(args) 1016 c.Assert(err, jc.ErrorIsNil) 1017 c.Assert(result, jc.DeepEquals, params.ErrorResults{ 1018 Results: []params.ErrorResult{ 1019 {¶ms.Error{ 1020 Message: `cannot record provisioning info for "i-was": cannot set instance data for machine "0": already set`, 1021 }}, 1022 {nil}, 1023 {nil}, 1024 {nil}, 1025 {apiservertesting.NotFoundError("machine 42")}, 1026 {apiservertesting.ErrUnauthorized}, 1027 {apiservertesting.ErrUnauthorized}, 1028 }, 1029 }) 1030 1031 // Verify machine 1 and 2 were provisioned. 1032 c.Assert(s.machines[1].Refresh(), gc.IsNil) 1033 c.Assert(s.machines[2].Refresh(), gc.IsNil) 1034 1035 instanceId, err := s.machines[1].InstanceId() 1036 c.Assert(err, jc.ErrorIsNil) 1037 c.Check(instanceId, gc.Equals, instance.Id("i-will")) 1038 instanceId, err = s.machines[2].InstanceId() 1039 c.Assert(err, jc.ErrorIsNil) 1040 c.Check(instanceId, gc.Equals, instance.Id("i-am-too")) 1041 c.Check(s.machines[1].CheckProvisioned("fake_nonce"), jc.IsTrue) 1042 c.Check(s.machines[2].CheckProvisioned("fake"), jc.IsTrue) 1043 gotHardware, err := s.machines[1].HardwareCharacteristics() 1044 c.Assert(err, jc.ErrorIsNil) 1045 c.Check(gotHardware, gc.DeepEquals, &hwChars) 1046 ifacesMachine1, err := s.machines[1].NetworkInterfaces() 1047 c.Assert(err, jc.ErrorIsNil) 1048 c.Assert(ifacesMachine1, gc.HasLen, 4) 1049 actual := make([]params.NetworkInterface, len(ifacesMachine1)) 1050 for i, iface := range ifacesMachine1 { 1051 actual[i].InterfaceName = iface.InterfaceName() 1052 actual[i].NetworkTag = iface.NetworkTag().String() 1053 actual[i].MACAddress = iface.MACAddress() 1054 actual[i].IsVirtual = iface.IsVirtual() 1055 actual[i].Disabled = iface.IsDisabled() 1056 c.Check(iface.MachineId(), gc.Equals, s.machines[1].Id()) 1057 c.Check(iface.MachineTag(), gc.Equals, s.machines[1].Tag()) 1058 } 1059 c.Assert(actual, jc.SameContents, ifaces[:4]) 1060 ifacesMachine2, err := s.machines[2].NetworkInterfaces() 1061 c.Assert(err, jc.ErrorIsNil) 1062 c.Assert(ifacesMachine2, gc.HasLen, 1) 1063 c.Assert(ifacesMachine2[0].InterfaceName(), gc.Equals, ifaces[5].InterfaceName) 1064 c.Assert(ifacesMachine2[0].MACAddress(), gc.Equals, ifaces[5].MACAddress) 1065 c.Assert(ifacesMachine2[0].NetworkTag().String(), gc.Equals, ifaces[5].NetworkTag) 1066 c.Assert(ifacesMachine2[0].MachineId(), gc.Equals, s.machines[2].Id()) 1067 for i := range networks { 1068 if i == 3 { 1069 // Last one was ignored, so don't check. 1070 break 1071 } 1072 tag, err := names.ParseNetworkTag(networks[i].Tag) 1073 c.Assert(err, jc.ErrorIsNil) 1074 networkName := tag.Id() 1075 network, err := s.State.Network(networkName) 1076 c.Assert(err, jc.ErrorIsNil) 1077 c.Check(network.Name(), gc.Equals, networkName) 1078 c.Check(network.ProviderId(), gc.Equals, networks[i].ProviderId) 1079 c.Check(network.Tag().String(), gc.Equals, networks[i].Tag) 1080 c.Check(network.VLANTag(), gc.Equals, networks[i].VLANTag) 1081 c.Check(network.CIDR(), gc.Equals, networks[i].CIDR) 1082 } 1083 1084 // Verify the machine with requested volumes was provisioned, and the 1085 // volume information recorded in state. 1086 blockDevices, err := volumesMachine.BlockDevices() 1087 c.Assert(err, jc.ErrorIsNil) 1088 c.Assert(blockDevices, gc.HasLen, 1) 1089 blockDeviceInfo, err := blockDevices[0].Info() 1090 c.Assert(err, jc.ErrorIsNil) 1091 c.Assert(blockDeviceInfo, gc.Equals, state.BlockDeviceInfo{Size: 1234}) 1092 1093 // Verify the machine without requested volumes still has no volumes 1094 // recorded in state. 1095 blockDevices, err = s.machines[1].BlockDevices() 1096 c.Assert(err, jc.ErrorIsNil) 1097 c.Assert(blockDevices, gc.HasLen, 0) 1098 } 1099 1100 func (s *withoutStateServerSuite) TestInstanceId(c *gc.C) { 1101 // Provision 2 machines first. 1102 err := s.machines[0].SetProvisioned("i-am", "fake_nonce", nil) 1103 c.Assert(err, jc.ErrorIsNil) 1104 hwChars := instance.MustParseHardware("arch=i386", "mem=4G") 1105 err = s.machines[1].SetProvisioned("i-am-not", "fake_nonce", &hwChars) 1106 c.Assert(err, jc.ErrorIsNil) 1107 1108 args := params.Entities{Entities: []params.Entity{ 1109 {Tag: s.machines[0].Tag().String()}, 1110 {Tag: s.machines[1].Tag().String()}, 1111 {Tag: s.machines[2].Tag().String()}, 1112 {Tag: "machine-42"}, 1113 {Tag: "unit-foo-0"}, 1114 {Tag: "service-bar"}, 1115 }} 1116 result, err := s.provisioner.InstanceId(args) 1117 c.Assert(err, jc.ErrorIsNil) 1118 c.Assert(result, gc.DeepEquals, params.StringResults{ 1119 Results: []params.StringResult{ 1120 {Result: "i-am"}, 1121 {Result: "i-am-not"}, 1122 {Error: apiservertesting.NotProvisionedError("2")}, 1123 {Error: apiservertesting.NotFoundError("machine 42")}, 1124 {Error: apiservertesting.ErrUnauthorized}, 1125 {Error: apiservertesting.ErrUnauthorized}, 1126 }, 1127 }) 1128 } 1129 1130 func (s *withoutStateServerSuite) TestWatchEnvironMachines(c *gc.C) { 1131 c.Assert(s.resources.Count(), gc.Equals, 0) 1132 1133 got, err := s.provisioner.WatchEnvironMachines() 1134 c.Assert(err, jc.ErrorIsNil) 1135 want := params.StringsWatchResult{ 1136 StringsWatcherId: "1", 1137 Changes: []string{"0", "1", "2", "3", "4"}, 1138 } 1139 c.Assert(got.StringsWatcherId, gc.Equals, want.StringsWatcherId) 1140 c.Assert(got.Changes, jc.SameContents, want.Changes) 1141 1142 // Verify the resources were registered and stop them when done. 1143 c.Assert(s.resources.Count(), gc.Equals, 1) 1144 resource := s.resources.Get("1") 1145 defer statetesting.AssertStop(c, resource) 1146 1147 // Check that the Watch has consumed the initial event ("returned" 1148 // in the Watch call) 1149 wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher)) 1150 wc.AssertNoChange() 1151 1152 // Make sure WatchEnvironMachines fails with a machine agent login. 1153 anAuthorizer := s.authorizer 1154 anAuthorizer.Tag = names.NewMachineTag("1") 1155 anAuthorizer.EnvironManager = false 1156 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 1157 c.Assert(err, jc.ErrorIsNil) 1158 1159 result, err := aProvisioner.WatchEnvironMachines() 1160 c.Assert(err, gc.ErrorMatches, "permission denied") 1161 c.Assert(result, gc.DeepEquals, params.StringsWatchResult{}) 1162 } 1163 1164 func (s *withoutStateServerSuite) TestContainerManagerConfig(c *gc.C) { 1165 args := params.ContainerManagerConfigParams{Type: instance.KVM} 1166 results, err := s.provisioner.ContainerManagerConfig(args) 1167 c.Check(err, jc.ErrorIsNil) 1168 c.Assert(results.ManagerConfig, gc.DeepEquals, map[string]string{ 1169 container.ConfigName: "juju", 1170 }) 1171 } 1172 1173 func (s *withoutStateServerSuite) TestContainerConfig(c *gc.C) { 1174 attrs := map[string]interface{}{ 1175 "http-proxy": "http://proxy.example.com:9000", 1176 } 1177 err := s.State.UpdateEnvironConfig(attrs, nil, nil) 1178 c.Assert(err, jc.ErrorIsNil) 1179 expectedProxy := proxy.Settings{ 1180 Http: "http://proxy.example.com:9000", 1181 } 1182 1183 results, err := s.provisioner.ContainerConfig() 1184 c.Check(err, jc.ErrorIsNil) 1185 c.Check(results.UpdateBehavior, gc.Not(gc.IsNil)) 1186 c.Check(results.ProviderType, gc.Equals, "dummy") 1187 c.Check(results.AuthorizedKeys, gc.Equals, s.Environ.Config().AuthorizedKeys()) 1188 c.Check(results.SSLHostnameVerification, jc.IsTrue) 1189 c.Check(results.Proxy, gc.DeepEquals, expectedProxy) 1190 c.Check(results.AptProxy, gc.DeepEquals, expectedProxy) 1191 c.Check(results.PreferIPv6, jc.IsTrue) 1192 } 1193 1194 func (s *withoutStateServerSuite) TestSetSupportedContainers(c *gc.C) { 1195 args := params.MachineContainersParams{ 1196 Params: []params.MachineContainers{ 1197 { 1198 MachineTag: "machine-0", 1199 ContainerTypes: []instance.ContainerType{instance.LXC}, 1200 }, 1201 { 1202 MachineTag: "machine-1", 1203 ContainerTypes: []instance.ContainerType{instance.LXC, instance.KVM}, 1204 }, 1205 }, 1206 } 1207 results, err := s.provisioner.SetSupportedContainers(args) 1208 c.Assert(err, jc.ErrorIsNil) 1209 c.Assert(results.Results, gc.HasLen, 2) 1210 for _, result := range results.Results { 1211 c.Assert(result.Error, gc.IsNil) 1212 } 1213 m0, err := s.State.Machine("0") 1214 c.Assert(err, jc.ErrorIsNil) 1215 containers, ok := m0.SupportedContainers() 1216 c.Assert(ok, jc.IsTrue) 1217 c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC}) 1218 m1, err := s.State.Machine("1") 1219 c.Assert(err, jc.ErrorIsNil) 1220 containers, ok = m1.SupportedContainers() 1221 c.Assert(ok, jc.IsTrue) 1222 c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC, instance.KVM}) 1223 } 1224 1225 func (s *withoutStateServerSuite) TestSetSupportedContainersPermissions(c *gc.C) { 1226 // Login as a machine agent for machine 0. 1227 anAuthorizer := s.authorizer 1228 anAuthorizer.EnvironManager = false 1229 anAuthorizer.Tag = s.machines[0].Tag() 1230 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 1231 c.Assert(err, jc.ErrorIsNil) 1232 c.Assert(aProvisioner, gc.NotNil) 1233 1234 args := params.MachineContainersParams{ 1235 Params: []params.MachineContainers{{ 1236 MachineTag: "machine-0", 1237 ContainerTypes: []instance.ContainerType{instance.LXC}, 1238 }, { 1239 MachineTag: "machine-1", 1240 ContainerTypes: []instance.ContainerType{instance.LXC}, 1241 }, { 1242 MachineTag: "machine-42", 1243 ContainerTypes: []instance.ContainerType{instance.LXC}, 1244 }, 1245 }, 1246 } 1247 // Only machine 0 can have it's containers updated. 1248 results, err := aProvisioner.SetSupportedContainers(args) 1249 c.Assert(results, gc.DeepEquals, params.ErrorResults{ 1250 Results: []params.ErrorResult{ 1251 {Error: nil}, 1252 {Error: apiservertesting.ErrUnauthorized}, 1253 {Error: apiservertesting.ErrUnauthorized}, 1254 }, 1255 }) 1256 } 1257 1258 func (s *withoutStateServerSuite) TestSupportsNoContainers(c *gc.C) { 1259 args := params.MachineContainersParams{ 1260 Params: []params.MachineContainers{ 1261 { 1262 MachineTag: "machine-0", 1263 }, 1264 }, 1265 } 1266 results, err := s.provisioner.SetSupportedContainers(args) 1267 c.Assert(err, jc.ErrorIsNil) 1268 c.Assert(results.Results, gc.HasLen, 1) 1269 c.Assert(results.Results[0].Error, gc.IsNil) 1270 m0, err := s.State.Machine("0") 1271 c.Assert(err, jc.ErrorIsNil) 1272 containers, ok := m0.SupportedContainers() 1273 c.Assert(ok, jc.IsTrue) 1274 c.Assert(containers, gc.DeepEquals, []instance.ContainerType{}) 1275 } 1276 1277 var _ = gc.Suite(&withStateServerSuite{}) 1278 1279 type withStateServerSuite struct { 1280 provisionerSuite 1281 } 1282 1283 func (s *withStateServerSuite) SetUpTest(c *gc.C) { 1284 s.provisionerSuite.setUpTest(c, true) 1285 } 1286 1287 func (s *withStateServerSuite) TestAPIAddresses(c *gc.C) { 1288 hostPorts := [][]network.HostPort{{{ 1289 Address: network.NewAddress("0.1.2.3", network.ScopeUnknown), 1290 Port: 1234, 1291 }}} 1292 1293 err := s.State.SetAPIHostPorts(hostPorts) 1294 c.Assert(err, jc.ErrorIsNil) 1295 1296 result, err := s.provisioner.APIAddresses() 1297 c.Assert(err, jc.ErrorIsNil) 1298 c.Assert(result, gc.DeepEquals, params.StringsResult{ 1299 Result: []string{"0.1.2.3:1234"}, 1300 }) 1301 } 1302 1303 func (s *withStateServerSuite) TestStateAddresses(c *gc.C) { 1304 addresses, err := s.State.Addresses() 1305 c.Assert(err, jc.ErrorIsNil) 1306 1307 result, err := s.provisioner.StateAddresses() 1308 c.Assert(err, jc.ErrorIsNil) 1309 c.Assert(result, gc.DeepEquals, params.StringsResult{ 1310 Result: addresses, 1311 }) 1312 } 1313 1314 func (s *withStateServerSuite) TestCACert(c *gc.C) { 1315 result := s.provisioner.CACert() 1316 c.Assert(result, gc.DeepEquals, params.BytesResult{ 1317 Result: []byte(s.State.CACert()), 1318 }) 1319 } 1320 1321 func (s *withoutStateServerSuite) TestWatchMachineErrorRetry(c *gc.C) { 1322 s.PatchValue(&provisioner.ErrorRetryWaitDelay, 2*coretesting.ShortWait) 1323 c.Assert(s.resources.Count(), gc.Equals, 0) 1324 1325 _, err := s.provisioner.WatchMachineErrorRetry() 1326 c.Assert(err, jc.ErrorIsNil) 1327 1328 // Verify the resources were registered and stop them when done. 1329 c.Assert(s.resources.Count(), gc.Equals, 1) 1330 resource := s.resources.Get("1") 1331 defer statetesting.AssertStop(c, resource) 1332 1333 // Check that the Watch has consumed the initial event ("returned" 1334 // in the Watch call) 1335 wc := statetesting.NewNotifyWatcherC(c, s.State, resource.(state.NotifyWatcher)) 1336 wc.AssertNoChange() 1337 1338 // We should now get a time triggered change. 1339 wc.AssertOneChange() 1340 1341 // Make sure WatchMachineErrorRetry fails with a machine agent login. 1342 anAuthorizer := s.authorizer 1343 anAuthorizer.Tag = names.NewMachineTag("1") 1344 anAuthorizer.EnvironManager = false 1345 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 1346 c.Assert(err, jc.ErrorIsNil) 1347 1348 result, err := aProvisioner.WatchMachineErrorRetry() 1349 c.Assert(err, gc.ErrorMatches, "permission denied") 1350 c.Assert(result, gc.DeepEquals, params.NotifyWatchResult{}) 1351 } 1352 1353 func (s *withoutStateServerSuite) TestFindTools(c *gc.C) { 1354 args := params.FindToolsParams{ 1355 MajorVersion: -1, 1356 MinorVersion: -1, 1357 } 1358 result, err := s.provisioner.FindTools(args) 1359 c.Assert(err, jc.ErrorIsNil) 1360 c.Assert(result.Error, gc.IsNil) 1361 c.Assert(result.List, gc.Not(gc.HasLen), 0) 1362 for _, tools := range result.List { 1363 url := fmt.Sprintf("https://%s/environment/%s/tools/%s", 1364 s.APIState.Addr(), coretesting.EnvironmentTag.Id(), tools.Version) 1365 c.Assert(tools.URL, gc.Equals, url) 1366 } 1367 }