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