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