github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/api/provisioner/provisioner_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 // TODO(anastasia) 2014-10-08 #1378716 5 // Re-enable tests for PPC64/ARM64 when the fixed gccgo has been backported to trusty and the CI machines have been updated. 6 7 // +build !gccgo 8 9 package provisioner_test 10 11 import ( 12 stdtesting "testing" 13 14 "github.com/juju/errors" 15 "github.com/juju/names" 16 jc "github.com/juju/testing/checkers" 17 "github.com/juju/utils" 18 gc "gopkg.in/check.v1" 19 20 "github.com/juju/juju/api" 21 "github.com/juju/juju/api/provisioner" 22 apitesting "github.com/juju/juju/api/testing" 23 "github.com/juju/juju/apiserver/common" 24 "github.com/juju/juju/apiserver/params" 25 "github.com/juju/juju/constraints" 26 "github.com/juju/juju/container" 27 "github.com/juju/juju/instance" 28 "github.com/juju/juju/juju/testing" 29 "github.com/juju/juju/mongo" 30 "github.com/juju/juju/network" 31 "github.com/juju/juju/state" 32 statetesting "github.com/juju/juju/state/testing" 33 coretesting "github.com/juju/juju/testing" 34 coretools "github.com/juju/juju/tools" 35 "github.com/juju/juju/version" 36 ) 37 38 func TestAll(t *stdtesting.T) { 39 coretesting.MgoTestPackage(t) 40 } 41 42 type provisionerSuite struct { 43 testing.JujuConnSuite 44 *apitesting.EnvironWatcherTests 45 *apitesting.APIAddresserTests 46 47 st *api.State 48 machine *state.Machine 49 50 provisioner *provisioner.State 51 } 52 53 var _ = gc.Suite(&provisionerSuite{}) 54 55 func (s *provisionerSuite) SetUpTest(c *gc.C) { 56 s.JujuConnSuite.SetUpTest(c) 57 58 var err error 59 s.machine, err = s.State.AddMachine("quantal", state.JobManageEnviron) 60 c.Assert(err, jc.ErrorIsNil) 61 password, err := utils.RandomPassword() 62 c.Assert(err, jc.ErrorIsNil) 63 err = s.machine.SetPassword(password) 64 c.Assert(err, jc.ErrorIsNil) 65 err = s.machine.SetInstanceInfo("i-manager", "fake_nonce", nil, nil, nil, nil) 66 c.Assert(err, jc.ErrorIsNil) 67 s.st = s.OpenAPIAsMachine(c, s.machine.Tag(), password, "fake_nonce") 68 c.Assert(s.st, gc.NotNil) 69 err = s.machine.SetAddresses(network.NewAddress("0.1.2.3", network.ScopeUnknown)) 70 c.Assert(err, jc.ErrorIsNil) 71 72 // Create the provisioner API facade. 73 s.provisioner = s.st.Provisioner() 74 c.Assert(s.provisioner, gc.NotNil) 75 76 s.EnvironWatcherTests = apitesting.NewEnvironWatcherTests(s.provisioner, s.BackingState, apitesting.HasSecrets) 77 s.APIAddresserTests = apitesting.NewAPIAddresserTests(s.provisioner, s.BackingState) 78 } 79 80 func (s *provisionerSuite) TestMachineTagAndId(c *gc.C) { 81 apiMachine, err := s.provisioner.Machine(names.NewMachineTag("42")) 82 c.Assert(err, gc.ErrorMatches, "machine 42 not found") 83 c.Assert(err, jc.Satisfies, params.IsCodeNotFound) 84 c.Assert(apiMachine, gc.IsNil) 85 86 // TODO(dfc) fix this type assertion 87 apiMachine, err = s.provisioner.Machine(s.machine.Tag().(names.MachineTag)) 88 c.Assert(err, jc.ErrorIsNil) 89 c.Assert(apiMachine.Tag(), gc.Equals, s.machine.Tag()) 90 c.Assert(apiMachine.Id(), gc.Equals, s.machine.Id()) 91 } 92 93 func (s *provisionerSuite) TestGetSetStatus(c *gc.C) { 94 apiMachine, err := s.provisioner.Machine(s.machine.Tag().(names.MachineTag)) 95 c.Assert(err, jc.ErrorIsNil) 96 97 status, info, err := apiMachine.Status() 98 c.Assert(err, jc.ErrorIsNil) 99 c.Assert(status, gc.Equals, params.StatusPending) 100 c.Assert(info, gc.Equals, "") 101 102 err = apiMachine.SetStatus(params.StatusStarted, "blah", nil) 103 c.Assert(err, jc.ErrorIsNil) 104 105 status, info, err = apiMachine.Status() 106 c.Assert(err, jc.ErrorIsNil) 107 c.Assert(status, gc.Equals, params.StatusStarted) 108 c.Assert(info, gc.Equals, "blah") 109 _, _, data, err := s.machine.Status() 110 c.Assert(err, jc.ErrorIsNil) 111 c.Assert(data, gc.HasLen, 0) 112 } 113 114 func (s *provisionerSuite) TestGetSetStatusWithData(c *gc.C) { 115 apiMachine, err := s.provisioner.Machine(s.machine.Tag().(names.MachineTag)) 116 c.Assert(err, jc.ErrorIsNil) 117 118 err = apiMachine.SetStatus(params.StatusError, "blah", map[string]interface{}{"foo": "bar"}) 119 c.Assert(err, jc.ErrorIsNil) 120 121 status, info, err := apiMachine.Status() 122 c.Assert(err, jc.ErrorIsNil) 123 c.Assert(status, gc.Equals, params.StatusError) 124 c.Assert(info, gc.Equals, "blah") 125 _, _, data, err := s.machine.Status() 126 c.Assert(err, jc.ErrorIsNil) 127 c.Assert(data, gc.DeepEquals, map[string]interface{}{"foo": "bar"}) 128 } 129 130 func (s *provisionerSuite) TestMachinesWithTransientErrors(c *gc.C) { 131 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 132 c.Assert(err, jc.ErrorIsNil) 133 err = machine.SetStatus(state.StatusError, "blah", map[string]interface{}{"transient": true}) 134 c.Assert(err, jc.ErrorIsNil) 135 machines, info, err := s.provisioner.MachinesWithTransientErrors() 136 c.Assert(err, jc.ErrorIsNil) 137 c.Assert(machines, gc.HasLen, 1) 138 c.Assert(machines[0].Id(), gc.Equals, "1") 139 c.Assert(info, gc.HasLen, 1) 140 c.Assert(info[0], gc.DeepEquals, params.StatusResult{ 141 Id: "1", 142 Life: "alive", 143 Status: "error", 144 Info: "blah", 145 Data: map[string]interface{}{"transient": true}, 146 }) 147 } 148 149 func (s *provisionerSuite) TestEnsureDeadAndRemove(c *gc.C) { 150 // Create a fresh machine to test the complete scenario. 151 otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits) 152 c.Assert(err, jc.ErrorIsNil) 153 c.Assert(otherMachine.Life(), gc.Equals, state.Alive) 154 155 apiMachine, err := s.provisioner.Machine(otherMachine.Tag().(names.MachineTag)) 156 c.Assert(err, jc.ErrorIsNil) 157 158 err = apiMachine.Remove() 159 c.Assert(err, gc.ErrorMatches, `cannot remove entity "machine-1": still alive`) 160 err = apiMachine.EnsureDead() 161 c.Assert(err, jc.ErrorIsNil) 162 163 err = otherMachine.Refresh() 164 c.Assert(err, jc.ErrorIsNil) 165 c.Assert(otherMachine.Life(), gc.Equals, state.Dead) 166 167 err = apiMachine.EnsureDead() 168 c.Assert(err, jc.ErrorIsNil) 169 err = otherMachine.Refresh() 170 c.Assert(err, jc.ErrorIsNil) 171 c.Assert(otherMachine.Life(), gc.Equals, state.Dead) 172 173 err = apiMachine.Remove() 174 c.Assert(err, jc.ErrorIsNil) 175 err = otherMachine.Refresh() 176 c.Assert(err, jc.Satisfies, errors.IsNotFound) 177 178 err = apiMachine.EnsureDead() 179 c.Assert(err, gc.ErrorMatches, "machine 1 not found") 180 c.Assert(err, jc.Satisfies, params.IsCodeNotFound) 181 182 // Now try to EnsureDead machine 0 - should fail. 183 apiMachine, err = s.provisioner.Machine(s.machine.Tag().(names.MachineTag)) 184 c.Assert(err, jc.ErrorIsNil) 185 err = apiMachine.EnsureDead() 186 c.Assert(err, gc.ErrorMatches, "machine 0 is required by the environment") 187 } 188 189 func (s *provisionerSuite) TestRefreshAndLife(c *gc.C) { 190 // Create a fresh machine to test the complete scenario. 191 otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits) 192 c.Assert(err, jc.ErrorIsNil) 193 c.Assert(otherMachine.Life(), gc.Equals, state.Alive) 194 195 apiMachine, err := s.provisioner.Machine(otherMachine.Tag().(names.MachineTag)) 196 c.Assert(err, jc.ErrorIsNil) 197 c.Assert(apiMachine.Life(), gc.Equals, params.Alive) 198 199 err = apiMachine.EnsureDead() 200 c.Assert(err, jc.ErrorIsNil) 201 c.Assert(apiMachine.Life(), gc.Equals, params.Alive) 202 203 err = apiMachine.Refresh() 204 c.Assert(err, jc.ErrorIsNil) 205 c.Assert(apiMachine.Life(), gc.Equals, params.Dead) 206 } 207 208 func (s *provisionerSuite) TestSetInstanceInfo(c *gc.C) { 209 // Create a fresh machine, since machine 0 is already provisioned. 210 notProvisionedMachine, err := s.State.AddMachine("quantal", state.JobHostUnits) 211 c.Assert(err, jc.ErrorIsNil) 212 213 apiMachine, err := s.provisioner.Machine(notProvisionedMachine.Tag().(names.MachineTag)) 214 c.Assert(err, jc.ErrorIsNil) 215 216 instanceId, err := apiMachine.InstanceId() 217 c.Assert(err, jc.Satisfies, params.IsCodeNotProvisioned) 218 c.Assert(err, gc.ErrorMatches, "machine 1 not provisioned") 219 c.Assert(instanceId, gc.Equals, instance.Id("")) 220 221 hwChars := instance.MustParseHardware("cpu-cores=123", "mem=4G") 222 223 _, err = s.State.Network("net1") 224 c.Assert(err, jc.Satisfies, errors.IsNotFound) 225 _, err = s.State.Network("vlan42") 226 c.Assert(err, jc.Satisfies, errors.IsNotFound) 227 228 ifacesMachine, err := notProvisionedMachine.NetworkInterfaces() 229 c.Assert(err, jc.ErrorIsNil) 230 c.Assert(ifacesMachine, gc.HasLen, 0) 231 232 networks := []params.Network{{ 233 Tag: "network-net1", 234 ProviderId: "net1", 235 CIDR: "0.1.2.0/24", 236 VLANTag: 0, 237 }, { 238 Tag: "network-vlan42", 239 ProviderId: "vlan42", 240 CIDR: "0.2.2.0/24", 241 VLANTag: 42, 242 }, { 243 Tag: "network-vlan69", 244 ProviderId: "vlan69", 245 CIDR: "0.3.2.0/24", 246 VLANTag: 69, 247 }, { 248 Tag: "network-vlan42", // duplicated; ignored 249 ProviderId: "vlan42", 250 CIDR: "0.2.2.0/24", 251 VLANTag: 42, 252 }} 253 ifaces := []params.NetworkInterface{{ 254 MACAddress: "aa:bb:cc:dd:ee:f0", 255 NetworkTag: "network-net1", 256 InterfaceName: "eth0", 257 IsVirtual: false, 258 }, { 259 MACAddress: "aa:bb:cc:dd:ee:f1", 260 NetworkTag: "network-net1", 261 InterfaceName: "eth1", 262 IsVirtual: false, 263 }, { 264 MACAddress: "aa:bb:cc:dd:ee:f1", 265 NetworkTag: "network-vlan42", 266 InterfaceName: "eth1.42", 267 IsVirtual: true, 268 }, { 269 MACAddress: "aa:bb:cc:dd:ee:f1", 270 NetworkTag: "network-vlan69", 271 InterfaceName: "eth1.69", 272 IsVirtual: true, 273 }, { 274 MACAddress: "aa:bb:cc:dd:ee:f1", // duplicated mac+net; ignored 275 NetworkTag: "network-vlan42", 276 InterfaceName: "eth2", 277 IsVirtual: true, 278 }, { 279 MACAddress: "aa:bb:cc:dd:ee:f4", 280 NetworkTag: "network-net1", 281 InterfaceName: "eth1", // duplicated name+machine id; ignored 282 IsVirtual: false, 283 }} 284 285 err = apiMachine.SetInstanceInfo("i-will", "fake_nonce", &hwChars, networks, ifaces, nil) 286 c.Assert(err, jc.ErrorIsNil) 287 288 instanceId, err = apiMachine.InstanceId() 289 c.Assert(err, jc.ErrorIsNil) 290 c.Assert(instanceId, gc.Equals, instance.Id("i-will")) 291 292 // Try it again - should fail. 293 err = apiMachine.SetInstanceInfo("i-wont", "fake", nil, nil, nil, nil) 294 c.Assert(err, gc.ErrorMatches, `cannot record provisioning info for "i-wont": cannot set instance data for machine "1": already set`) 295 296 // Now try to get machine 0's instance id. 297 apiMachine, err = s.provisioner.Machine(s.machine.Tag().(names.MachineTag)) 298 c.Assert(err, jc.ErrorIsNil) 299 instanceId, err = apiMachine.InstanceId() 300 c.Assert(err, jc.ErrorIsNil) 301 c.Assert(instanceId, gc.Equals, instance.Id("i-manager")) 302 303 // Check the networks are created. 304 for i := range networks { 305 if i == 3 { 306 // Last one was ignored, so skip it. 307 break 308 } 309 tag, err := names.ParseNetworkTag(networks[i].Tag) 310 c.Assert(err, jc.ErrorIsNil) 311 networkName := tag.Id() 312 network, err := s.State.Network(networkName) 313 c.Assert(err, jc.ErrorIsNil) 314 c.Check(network.Name(), gc.Equals, networkName) 315 c.Check(network.ProviderId(), gc.Equals, networks[i].ProviderId) 316 c.Check(network.Tag().String(), gc.Equals, networks[i].Tag) 317 c.Check(network.VLANTag(), gc.Equals, networks[i].VLANTag) 318 c.Check(network.CIDR(), gc.Equals, networks[i].CIDR) 319 } 320 321 // And the network interfaces as well. 322 ifacesMachine, err = notProvisionedMachine.NetworkInterfaces() 323 c.Assert(err, jc.ErrorIsNil) 324 c.Assert(ifacesMachine, gc.HasLen, 4) 325 actual := make([]params.NetworkInterface, len(ifacesMachine)) 326 for i, iface := range ifacesMachine { 327 actual[i].InterfaceName = iface.InterfaceName() 328 actual[i].NetworkTag = iface.NetworkTag().String() 329 actual[i].MACAddress = iface.MACAddress() 330 actual[i].IsVirtual = iface.IsVirtual() 331 c.Check(iface.MachineTag(), gc.Equals, notProvisionedMachine.Tag()) 332 c.Check(iface.MachineId(), gc.Equals, notProvisionedMachine.Id()) 333 } 334 c.Assert(actual, jc.SameContents, ifaces[:4]) // skip the rest as they are ignored. 335 } 336 337 func (s *provisionerSuite) TestSeries(c *gc.C) { 338 // Create a fresh machine with different series. 339 foobarMachine, err := s.State.AddMachine("foobar", state.JobHostUnits) 340 c.Assert(err, jc.ErrorIsNil) 341 342 apiMachine, err := s.provisioner.Machine(foobarMachine.Tag().(names.MachineTag)) 343 c.Assert(err, jc.ErrorIsNil) 344 series, err := apiMachine.Series() 345 c.Assert(err, jc.ErrorIsNil) 346 c.Assert(series, gc.Equals, "foobar") 347 348 // Now try machine 0. 349 apiMachine, err = s.provisioner.Machine(s.machine.Tag().(names.MachineTag)) 350 c.Assert(err, jc.ErrorIsNil) 351 series, err = apiMachine.Series() 352 c.Assert(err, jc.ErrorIsNil) 353 c.Assert(series, gc.Equals, "quantal") 354 } 355 356 func (s *provisionerSuite) TestDistributionGroup(c *gc.C) { 357 apiMachine, err := s.provisioner.Machine(s.machine.Tag().(names.MachineTag)) 358 c.Assert(err, jc.ErrorIsNil) 359 instances, err := apiMachine.DistributionGroup() 360 c.Assert(err, jc.ErrorIsNil) 361 c.Assert(instances, gc.DeepEquals, []instance.Id{"i-manager"}) 362 363 machine1, err := s.State.AddMachine("quantal", state.JobHostUnits) 364 c.Assert(err, jc.ErrorIsNil) 365 apiMachine, err = s.provisioner.Machine(machine1.Tag().(names.MachineTag)) 366 c.Assert(err, jc.ErrorIsNil) 367 wordpress := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 368 369 err = apiMachine.SetInstanceInfo("i-d", "fake", nil, nil, nil, nil) 370 c.Assert(err, jc.ErrorIsNil) 371 instances, err = apiMachine.DistributionGroup() 372 c.Assert(err, jc.ErrorIsNil) 373 c.Assert(instances, gc.HasLen, 0) // no units assigned 374 375 var unitNames []string 376 for i := 0; i < 3; i++ { 377 unit, err := wordpress.AddUnit() 378 c.Assert(err, jc.ErrorIsNil) 379 unitNames = append(unitNames, unit.Name()) 380 err = unit.AssignToMachine(machine1) 381 c.Assert(err, jc.ErrorIsNil) 382 instances, err := apiMachine.DistributionGroup() 383 c.Assert(err, jc.ErrorIsNil) 384 c.Assert(instances, gc.DeepEquals, []instance.Id{"i-d"}) 385 } 386 } 387 388 func (s *provisionerSuite) TestDistributionGroupMachineNotFound(c *gc.C) { 389 stateMachine, err := s.State.AddMachine("quantal", state.JobHostUnits) 390 c.Assert(err, jc.ErrorIsNil) 391 apiMachine, err := s.provisioner.Machine(stateMachine.Tag().(names.MachineTag)) 392 c.Assert(err, jc.ErrorIsNil) 393 err = apiMachine.EnsureDead() 394 c.Assert(err, jc.ErrorIsNil) 395 err = apiMachine.Remove() 396 c.Assert(err, jc.ErrorIsNil) 397 _, err = apiMachine.DistributionGroup() 398 c.Assert(err, gc.ErrorMatches, "machine 1 not found") 399 c.Assert(err, jc.Satisfies, params.IsCodeNotFound) 400 } 401 402 func (s *provisionerSuite) TestProvisioningInfo(c *gc.C) { 403 cons := constraints.MustParse("cpu-cores=12 mem=8G networks=^net3,^net4") 404 template := state.MachineTemplate{ 405 Series: "quantal", 406 Jobs: []state.MachineJob{state.JobHostUnits}, 407 Placement: "valid", 408 Constraints: cons, 409 RequestedNetworks: []string{"net1", "net2"}, 410 } 411 machine, err := s.State.AddOneMachine(template) 412 c.Assert(err, jc.ErrorIsNil) 413 apiMachine, err := s.provisioner.Machine(machine.Tag().(names.MachineTag)) 414 c.Assert(err, jc.ErrorIsNil) 415 provisioningInfo, err := apiMachine.ProvisioningInfo() 416 c.Assert(err, jc.ErrorIsNil) 417 c.Assert(provisioningInfo.Series, gc.Equals, template.Series) 418 c.Assert(provisioningInfo.Placement, gc.Equals, template.Placement) 419 c.Assert(provisioningInfo.Constraints, gc.DeepEquals, template.Constraints) 420 c.Assert(provisioningInfo.Networks, gc.DeepEquals, template.RequestedNetworks) 421 } 422 423 func (s *provisionerSuite) TestProvisioningInfoMachineNotFound(c *gc.C) { 424 stateMachine, err := s.State.AddMachine("quantal", state.JobHostUnits) 425 c.Assert(err, jc.ErrorIsNil) 426 apiMachine, err := s.provisioner.Machine(stateMachine.Tag().(names.MachineTag)) 427 c.Assert(err, jc.ErrorIsNil) 428 err = apiMachine.EnsureDead() 429 c.Assert(err, jc.ErrorIsNil) 430 err = apiMachine.Remove() 431 c.Assert(err, jc.ErrorIsNil) 432 _, err = apiMachine.ProvisioningInfo() 433 c.Assert(err, gc.ErrorMatches, "machine 1 not found") 434 c.Assert(err, jc.Satisfies, params.IsCodeNotFound) 435 // auth tests in apiserver 436 } 437 438 func (s *provisionerSuite) TestWatchContainers(c *gc.C) { 439 apiMachine, err := s.provisioner.Machine(s.machine.Tag().(names.MachineTag)) 440 c.Assert(err, jc.ErrorIsNil) 441 442 // Add one LXC container. 443 template := state.MachineTemplate{ 444 Series: "quantal", 445 Jobs: []state.MachineJob{state.JobHostUnits}, 446 } 447 container, err := s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC) 448 c.Assert(err, jc.ErrorIsNil) 449 450 w, err := apiMachine.WatchContainers(instance.LXC) 451 c.Assert(err, jc.ErrorIsNil) 452 defer statetesting.AssertStop(c, w) 453 wc := statetesting.NewStringsWatcherC(c, s.BackingState, w) 454 455 // Initial event. 456 wc.AssertChange(container.Id()) 457 458 // Change something other than the containers and make sure it's 459 // not detected. 460 err = apiMachine.SetStatus(params.StatusStarted, "not really", nil) 461 c.Assert(err, jc.ErrorIsNil) 462 wc.AssertNoChange() 463 464 // Add a KVM container and make sure it's not detected. 465 container, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.KVM) 466 c.Assert(err, jc.ErrorIsNil) 467 wc.AssertNoChange() 468 469 // Add another LXC container and make sure it's detected. 470 container, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC) 471 c.Assert(err, jc.ErrorIsNil) 472 wc.AssertChange(container.Id()) 473 474 statetesting.AssertStop(c, w) 475 wc.AssertClosed() 476 } 477 478 func (s *provisionerSuite) TestWatchContainersAcceptsSupportedContainers(c *gc.C) { 479 apiMachine, err := s.provisioner.Machine(s.machine.Tag().(names.MachineTag)) 480 c.Assert(err, jc.ErrorIsNil) 481 482 for _, ctype := range instance.ContainerTypes { 483 w, err := apiMachine.WatchContainers(ctype) 484 c.Assert(w, gc.NotNil) 485 c.Assert(err, jc.ErrorIsNil) 486 } 487 } 488 489 func (s *provisionerSuite) TestWatchContainersErrors(c *gc.C) { 490 apiMachine, err := s.provisioner.Machine(s.machine.Tag().(names.MachineTag)) 491 c.Assert(err, jc.ErrorIsNil) 492 493 _, err = apiMachine.WatchContainers(instance.NONE) 494 c.Assert(err, gc.ErrorMatches, `unsupported container type "none"`) 495 496 _, err = apiMachine.WatchContainers("") 497 c.Assert(err, gc.ErrorMatches, "container type must be specified") 498 } 499 500 func (s *provisionerSuite) TestWatchEnvironMachines(c *gc.C) { 501 w, err := s.provisioner.WatchEnvironMachines() 502 c.Assert(err, jc.ErrorIsNil) 503 defer statetesting.AssertStop(c, w) 504 wc := statetesting.NewStringsWatcherC(c, s.BackingState, w) 505 506 // Initial event. 507 wc.AssertChange(s.machine.Id()) 508 509 // Add another 2 machines make sure they are detected. 510 otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits) 511 c.Assert(err, jc.ErrorIsNil) 512 otherMachine, err = s.State.AddMachine("quantal", state.JobHostUnits) 513 c.Assert(err, jc.ErrorIsNil) 514 wc.AssertChange("1", "2") 515 516 // Change the lifecycle of last machine. 517 err = otherMachine.EnsureDead() 518 c.Assert(err, jc.ErrorIsNil) 519 wc.AssertChange("2") 520 521 // Add a container and make sure it's not detected. 522 template := state.MachineTemplate{ 523 Series: "quantal", 524 Jobs: []state.MachineJob{state.JobHostUnits}, 525 } 526 _, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC) 527 c.Assert(err, jc.ErrorIsNil) 528 wc.AssertNoChange() 529 530 statetesting.AssertStop(c, w) 531 wc.AssertClosed() 532 } 533 534 func (s *provisionerSuite) TestStateAddresses(c *gc.C) { 535 err := s.machine.SetAddresses(network.NewAddress("0.1.2.3", network.ScopeUnknown)) 536 c.Assert(err, jc.ErrorIsNil) 537 538 stateAddresses, err := s.State.Addresses() 539 c.Assert(err, jc.ErrorIsNil) 540 541 addresses, err := s.provisioner.StateAddresses() 542 c.Assert(err, jc.ErrorIsNil) 543 c.Assert(addresses, gc.DeepEquals, stateAddresses) 544 } 545 546 func (s *provisionerSuite) TestContainerManagerConfigKVM(c *gc.C) { 547 args := params.ContainerManagerConfigParams{Type: instance.KVM} 548 result, err := s.provisioner.ContainerManagerConfig(args) 549 c.Assert(err, jc.ErrorIsNil) 550 c.Assert(result.ManagerConfig, gc.DeepEquals, map[string]string{ 551 container.ConfigName: "juju", 552 }) 553 } 554 555 func (s *provisionerSuite) TestContainerManagerConfigLXC(c *gc.C) { 556 args := params.ContainerManagerConfigParams{Type: instance.LXC} 557 st, err := state.Open(s.MongoInfo(c), mongo.DialOpts{}, state.Policy(nil)) 558 c.Assert(err, jc.ErrorIsNil) 559 defer st.Close() 560 561 tests := []struct { 562 lxcUseClone bool 563 lxcUseCloneAufs bool 564 expectedUseClone string 565 expectedUseCloneAufs string 566 }{{ 567 lxcUseClone: true, 568 expectedUseClone: "true", 569 expectedUseCloneAufs: "false", 570 }, { 571 lxcUseClone: false, 572 expectedUseClone: "false", 573 expectedUseCloneAufs: "false", 574 }, { 575 lxcUseCloneAufs: false, 576 expectedUseClone: "false", 577 expectedUseCloneAufs: "false", 578 }, { 579 lxcUseClone: true, 580 lxcUseCloneAufs: true, 581 expectedUseClone: "true", 582 expectedUseCloneAufs: "true", 583 }} 584 585 result, err := s.provisioner.ContainerManagerConfig(args) 586 c.Assert(err, jc.ErrorIsNil) 587 c.Assert(result.ManagerConfig[container.ConfigName], gc.Equals, "juju") 588 c.Assert(result.ManagerConfig["use-clone"], gc.Equals, "") 589 590 // Change lxc-clone, and ensure it gets picked up. 591 for i, t := range tests { 592 c.Logf("test %d: %+v", i, t) 593 err = st.UpdateEnvironConfig(map[string]interface{}{ 594 "lxc-clone": t.lxcUseClone, 595 "lxc-clone-aufs": t.lxcUseCloneAufs, 596 }, nil, nil) 597 c.Assert(err, jc.ErrorIsNil) 598 result, err := s.provisioner.ContainerManagerConfig(args) 599 c.Assert(err, jc.ErrorIsNil) 600 c.Assert(result.ManagerConfig[container.ConfigName], gc.Equals, "juju") 601 c.Assert(result.ManagerConfig["use-clone"], gc.Equals, t.expectedUseClone) 602 c.Assert(result.ManagerConfig["use-aufs"], gc.Equals, t.expectedUseCloneAufs) 603 } 604 } 605 606 func (s *provisionerSuite) TestContainerManagerConfigPermissive(c *gc.C) { 607 // ContainerManagerConfig is permissive of container types, and 608 // will just return the basic type-independent configuration. 609 args := params.ContainerManagerConfigParams{Type: "invalid"} 610 result, err := s.provisioner.ContainerManagerConfig(args) 611 c.Assert(err, jc.ErrorIsNil) 612 c.Assert(result.ManagerConfig, gc.DeepEquals, map[string]string{ 613 container.ConfigName: "juju", 614 }) 615 } 616 617 func (s *provisionerSuite) TestContainerConfig(c *gc.C) { 618 result, err := s.provisioner.ContainerConfig() 619 c.Assert(err, jc.ErrorIsNil) 620 c.Assert(result.ProviderType, gc.Equals, "dummy") 621 c.Assert(result.AuthorizedKeys, gc.Equals, s.Environ.Config().AuthorizedKeys()) 622 c.Assert(result.SSLHostnameVerification, jc.IsTrue) 623 c.Assert(result.PreferIPv6, jc.IsTrue) 624 } 625 626 func (s *provisionerSuite) TestSetSupportedContainers(c *gc.C) { 627 apiMachine, err := s.provisioner.Machine(s.machine.Tag().(names.MachineTag)) 628 c.Assert(err, jc.ErrorIsNil) 629 err = apiMachine.SetSupportedContainers(instance.LXC, instance.KVM) 630 c.Assert(err, jc.ErrorIsNil) 631 632 err = s.machine.Refresh() 633 c.Assert(err, jc.ErrorIsNil) 634 containers, ok := s.machine.SupportedContainers() 635 c.Assert(ok, jc.IsTrue) 636 c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC, instance.KVM}) 637 } 638 639 func (s *provisionerSuite) TestSupportsNoContainers(c *gc.C) { 640 apiMachine, err := s.provisioner.Machine(s.machine.Tag().(names.MachineTag)) 641 c.Assert(err, jc.ErrorIsNil) 642 err = apiMachine.SupportsNoContainers() 643 c.Assert(err, jc.ErrorIsNil) 644 645 err = s.machine.Refresh() 646 c.Assert(err, jc.ErrorIsNil) 647 containers, ok := s.machine.SupportedContainers() 648 c.Assert(ok, jc.IsTrue) 649 c.Assert(containers, gc.DeepEquals, []instance.ContainerType{}) 650 } 651 652 func (s *provisionerSuite) TestFindToolsNoArch(c *gc.C) { 653 s.testFindTools(c, false, nil, nil) 654 } 655 656 func (s *provisionerSuite) TestFindToolsArch(c *gc.C) { 657 s.testFindTools(c, true, nil, nil) 658 } 659 660 func (s *provisionerSuite) TestFindToolsAPIError(c *gc.C) { 661 apiError := errors.New("everything's broken") 662 s.testFindTools(c, false, apiError, nil) 663 } 664 665 func (s *provisionerSuite) TestFindToolsLogicError(c *gc.C) { 666 logicError := errors.NotFoundf("tools") 667 s.testFindTools(c, false, nil, logicError) 668 } 669 670 func (s *provisionerSuite) testFindTools(c *gc.C, matchArch bool, apiError, logicError error) { 671 var toolsList = coretools.List{&coretools.Tools{Version: version.Current}} 672 var called bool 673 provisioner.PatchFacadeCall(s, s.provisioner, func(request string, args, response interface{}) error { 674 called = true 675 c.Assert(request, gc.Equals, "FindTools") 676 expected := params.FindToolsParams{ 677 Number: version.Current.Number, 678 Series: version.Current.Series, 679 MinorVersion: -1, 680 MajorVersion: -1, 681 } 682 if matchArch { 683 expected.Arch = version.Current.Arch 684 } 685 c.Assert(args, gc.Equals, expected) 686 result := response.(*params.FindToolsResult) 687 result.List = toolsList 688 if logicError != nil { 689 result.Error = common.ServerError(logicError) 690 } 691 return apiError 692 }) 693 694 var arch *string 695 if matchArch { 696 arch = &version.Current.Arch 697 } 698 apiList, err := s.provisioner.FindTools(version.Current.Number, version.Current.Series, arch) 699 c.Assert(called, jc.IsTrue) 700 if apiError != nil { 701 c.Assert(err, gc.Equals, apiError) 702 } else if logicError != nil { 703 c.Assert(err.Error(), gc.Equals, logicError.Error()) 704 } else { 705 c.Assert(err, jc.ErrorIsNil) 706 c.Assert(apiList, jc.SameContents, toolsList) 707 } 708 }