github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/environs/jujutest/livetests.go (about)

     1  // Copyright 2011, 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package jujutest
     5  
     6  import (
     7  	"fmt"
     8  	"time"
     9  
    10  	"github.com/juju/errors"
    11  	gitjujutesting "github.com/juju/testing"
    12  	jc "github.com/juju/testing/checkers"
    13  	"github.com/juju/utils"
    14  	gc "gopkg.in/check.v1"
    15  	"gopkg.in/juju/charmrepo.v1"
    16  
    17  	"github.com/juju/juju/api"
    18  	"github.com/juju/juju/cloudconfig/instancecfg"
    19  	"github.com/juju/juju/constraints"
    20  	"github.com/juju/juju/environs"
    21  	"github.com/juju/juju/environs/bootstrap"
    22  	"github.com/juju/juju/environs/config"
    23  	"github.com/juju/juju/environs/configstore"
    24  	"github.com/juju/juju/environs/filestorage"
    25  	"github.com/juju/juju/environs/storage"
    26  	"github.com/juju/juju/environs/sync"
    27  	envtesting "github.com/juju/juju/environs/testing"
    28  	envtools "github.com/juju/juju/environs/tools"
    29  	envtoolstesting "github.com/juju/juju/environs/tools/testing"
    30  	"github.com/juju/juju/instance"
    31  	"github.com/juju/juju/juju"
    32  	jujutesting "github.com/juju/juju/juju/testing"
    33  	"github.com/juju/juju/network"
    34  	"github.com/juju/juju/provider/dummy"
    35  	"github.com/juju/juju/state"
    36  	statetesting "github.com/juju/juju/state/testing"
    37  	"github.com/juju/juju/testcharms"
    38  	coretesting "github.com/juju/juju/testing"
    39  	coretools "github.com/juju/juju/tools"
    40  	"github.com/juju/juju/version"
    41  )
    42  
    43  // LiveTests contains tests that are designed to run against a live server
    44  // (e.g. Amazon EC2).  The Environ is opened once only for all the tests
    45  // in the suite, stored in Env, and Destroyed after the suite has completed.
    46  type LiveTests struct {
    47  	gitjujutesting.CleanupSuite
    48  
    49  	envtesting.ToolsFixture
    50  
    51  	// TestConfig contains the configuration attributes for opening an environment.
    52  	TestConfig coretesting.Attrs
    53  
    54  	// Attempt holds a strategy for waiting until the environment
    55  	// becomes logically consistent.
    56  	Attempt utils.AttemptStrategy
    57  
    58  	// CanOpenState should be true if the testing environment allows
    59  	// the state to be opened after bootstrapping.
    60  	CanOpenState bool
    61  
    62  	// HasProvisioner should be true if the environment has
    63  	// a provisioning agent.
    64  	HasProvisioner bool
    65  
    66  	// Env holds the currently opened environment.
    67  	// This is set by PrepareOnce and BootstrapOnce.
    68  	Env environs.Environ
    69  
    70  	// ConfigStore holds the configuration storage
    71  	// used when preparing the environment.
    72  	// This is initialized by SetUpSuite.
    73  	ConfigStore configstore.Storage
    74  
    75  	prepared     bool
    76  	bootstrapped bool
    77  	toolsStorage storage.Storage
    78  }
    79  
    80  func (t *LiveTests) SetUpSuite(c *gc.C) {
    81  	t.CleanupSuite.SetUpSuite(c)
    82  	t.ConfigStore = configstore.NewMem()
    83  }
    84  
    85  func (t *LiveTests) SetUpTest(c *gc.C) {
    86  	t.CleanupSuite.SetUpTest(c)
    87  	t.PatchValue(&version.Current.Number, coretesting.FakeVersionNumber)
    88  	storageDir := c.MkDir()
    89  	t.DefaultBaseURL = "file://" + storageDir + "/tools"
    90  	t.ToolsFixture.SetUpTest(c)
    91  	stor, err := filestorage.NewFileStorageWriter(storageDir)
    92  	c.Assert(err, jc.ErrorIsNil)
    93  	t.UploadFakeTools(c, stor, "released", "released")
    94  	t.toolsStorage = stor
    95  	t.CleanupSuite.PatchValue(&envtools.BundleTools, envtoolstesting.GetMockBundleTools(c))
    96  }
    97  
    98  func publicAttrs(e environs.Environ) map[string]interface{} {
    99  	cfg := e.Config()
   100  	secrets, err := e.Provider().SecretAttrs(cfg)
   101  	if err != nil {
   102  		panic(err)
   103  	}
   104  	attrs := cfg.AllAttrs()
   105  	for attr := range secrets {
   106  		delete(attrs, attr)
   107  	}
   108  	return attrs
   109  }
   110  
   111  func (t *LiveTests) TearDownSuite(c *gc.C) {
   112  	t.Destroy(c)
   113  	t.CleanupSuite.TearDownSuite(c)
   114  }
   115  
   116  func (t *LiveTests) TearDownTest(c *gc.C) {
   117  	t.ToolsFixture.TearDownTest(c)
   118  	t.CleanupSuite.TearDownTest(c)
   119  }
   120  
   121  // PrepareOnce ensures that the environment is
   122  // available and prepared. It sets t.Env appropriately.
   123  func (t *LiveTests) PrepareOnce(c *gc.C) {
   124  	if t.prepared {
   125  		return
   126  	}
   127  	cfg, err := config.New(config.NoDefaults, t.TestConfig)
   128  	c.Assert(err, jc.ErrorIsNil)
   129  	e, err := environs.Prepare(cfg, envtesting.BootstrapContext(c), t.ConfigStore)
   130  	c.Assert(err, gc.IsNil, gc.Commentf("preparing environ %#v", t.TestConfig))
   131  	c.Assert(e, gc.NotNil)
   132  	t.Env = e
   133  	t.prepared = true
   134  }
   135  
   136  func (t *LiveTests) BootstrapOnce(c *gc.C) {
   137  	if t.bootstrapped {
   138  		return
   139  	}
   140  	t.PrepareOnce(c)
   141  	// We only build and upload tools if there will be a state agent that
   142  	// we could connect to (actual live tests, rather than local-only)
   143  	cons := constraints.MustParse("mem=2G")
   144  	if t.CanOpenState {
   145  		_, err := sync.Upload(t.toolsStorage, "released", nil, coretesting.FakeDefaultSeries)
   146  		c.Assert(err, jc.ErrorIsNil)
   147  	}
   148  	err := bootstrap.EnsureNotBootstrapped(t.Env)
   149  	c.Assert(err, jc.ErrorIsNil)
   150  	err = bootstrap.Bootstrap(envtesting.BootstrapContext(c), t.Env, bootstrap.BootstrapParams{Constraints: cons})
   151  	c.Assert(err, jc.ErrorIsNil)
   152  	t.bootstrapped = true
   153  }
   154  
   155  func (t *LiveTests) Destroy(c *gc.C) {
   156  	if t.Env == nil {
   157  		return
   158  	}
   159  	err := environs.Destroy(t.Env, t.ConfigStore)
   160  	c.Assert(err, jc.ErrorIsNil)
   161  	t.bootstrapped = false
   162  	t.prepared = false
   163  	t.Env = nil
   164  }
   165  
   166  func (t *LiveTests) TestPrechecker(c *gc.C) {
   167  	// Providers may implement Prechecker. If they do, then they should
   168  	// return nil for empty constraints (excluding the null provider).
   169  	prechecker, ok := t.Env.(state.Prechecker)
   170  	if !ok {
   171  		return
   172  	}
   173  	const placement = ""
   174  	err := prechecker.PrecheckInstance("precise", constraints.Value{}, placement)
   175  	c.Assert(err, jc.ErrorIsNil)
   176  }
   177  
   178  // TestStartStop is similar to Tests.TestStartStop except
   179  // that it does not assume a pristine environment.
   180  func (t *LiveTests) TestStartStop(c *gc.C) {
   181  	t.BootstrapOnce(c)
   182  
   183  	inst, _ := jujutesting.AssertStartInstance(c, t.Env, "0")
   184  	c.Assert(inst, gc.NotNil)
   185  	id0 := inst.Id()
   186  
   187  	insts, err := t.Env.Instances([]instance.Id{id0, id0})
   188  	c.Assert(err, jc.ErrorIsNil)
   189  	c.Assert(insts, gc.HasLen, 2)
   190  	c.Assert(insts[0].Id(), gc.Equals, id0)
   191  	c.Assert(insts[1].Id(), gc.Equals, id0)
   192  
   193  	// Asserting on the return of AllInstances makes the test fragile,
   194  	// as even comparing the before and after start values can be thrown
   195  	// off if other instances have been created or destroyed in the same
   196  	// time frame. Instead, just check the instance we created exists.
   197  	insts, err = t.Env.AllInstances()
   198  	c.Assert(err, jc.ErrorIsNil)
   199  	found := false
   200  	for _, inst := range insts {
   201  		if inst.Id() == id0 {
   202  			c.Assert(found, gc.Equals, false, gc.Commentf("%v", insts))
   203  			found = true
   204  		}
   205  	}
   206  	c.Assert(found, gc.Equals, true, gc.Commentf("expected %v in %v", inst, insts))
   207  
   208  	addresses, err := jujutesting.WaitInstanceAddresses(t.Env, inst.Id())
   209  	c.Assert(err, jc.ErrorIsNil)
   210  	c.Assert(addresses, gc.Not(gc.HasLen), 0)
   211  
   212  	insts, err = t.Env.Instances([]instance.Id{id0, ""})
   213  	c.Assert(err, gc.Equals, environs.ErrPartialInstances)
   214  	c.Assert(insts, gc.HasLen, 2)
   215  	c.Check(insts[0].Id(), gc.Equals, id0)
   216  	c.Check(insts[1], gc.IsNil)
   217  
   218  	err = t.Env.StopInstances(inst.Id())
   219  	c.Assert(err, jc.ErrorIsNil)
   220  
   221  	// The machine may not be marked as shutting down
   222  	// immediately. Repeat a few times to ensure we get the error.
   223  	for a := t.Attempt.Start(); a.Next(); {
   224  		insts, err = t.Env.Instances([]instance.Id{id0})
   225  		if err != nil {
   226  			break
   227  		}
   228  	}
   229  	c.Assert(err, gc.Equals, environs.ErrNoInstances)
   230  	c.Assert(insts, gc.HasLen, 0)
   231  }
   232  
   233  func (t *LiveTests) TestPorts(c *gc.C) {
   234  	t.BootstrapOnce(c)
   235  
   236  	inst1, _ := jujutesting.AssertStartInstance(c, t.Env, "1")
   237  	c.Assert(inst1, gc.NotNil)
   238  	defer t.Env.StopInstances(inst1.Id())
   239  	ports, err := inst1.Ports("1")
   240  	c.Assert(err, jc.ErrorIsNil)
   241  	c.Assert(ports, gc.HasLen, 0)
   242  
   243  	inst2, _ := jujutesting.AssertStartInstance(c, t.Env, "2")
   244  	c.Assert(inst2, gc.NotNil)
   245  	ports, err = inst2.Ports("2")
   246  	c.Assert(err, jc.ErrorIsNil)
   247  	c.Assert(ports, gc.HasLen, 0)
   248  	defer t.Env.StopInstances(inst2.Id())
   249  
   250  	// Open some ports and check they're there.
   251  	err = inst1.OpenPorts("1", []network.PortRange{{67, 67, "udp"}, {45, 45, "tcp"}, {80, 100, "tcp"}})
   252  	c.Assert(err, jc.ErrorIsNil)
   253  	ports, err = inst1.Ports("1")
   254  	c.Assert(err, jc.ErrorIsNil)
   255  	c.Assert(ports, gc.DeepEquals, []network.PortRange{{45, 45, "tcp"}, {80, 100, "tcp"}, {67, 67, "udp"}})
   256  	ports, err = inst2.Ports("2")
   257  	c.Assert(err, jc.ErrorIsNil)
   258  	c.Assert(ports, gc.HasLen, 0)
   259  
   260  	err = inst2.OpenPorts("2", []network.PortRange{{89, 89, "tcp"}, {45, 45, "tcp"}, {20, 30, "tcp"}})
   261  	c.Assert(err, jc.ErrorIsNil)
   262  
   263  	// Check there's no crosstalk to another machine
   264  	ports, err = inst2.Ports("2")
   265  	c.Assert(err, jc.ErrorIsNil)
   266  	c.Assert(ports, gc.DeepEquals, []network.PortRange{{20, 30, "tcp"}, {45, 45, "tcp"}, {89, 89, "tcp"}})
   267  	ports, err = inst1.Ports("1")
   268  	c.Assert(err, jc.ErrorIsNil)
   269  	c.Assert(ports, gc.DeepEquals, []network.PortRange{{45, 45, "tcp"}, {80, 100, "tcp"}, {67, 67, "udp"}})
   270  
   271  	// Check that opening the same port again is ok.
   272  	oldPorts, err := inst2.Ports("2")
   273  	c.Assert(err, jc.ErrorIsNil)
   274  	err = inst2.OpenPorts("2", []network.PortRange{{45, 45, "tcp"}})
   275  	c.Assert(err, jc.ErrorIsNil)
   276  	err = inst2.OpenPorts("2", []network.PortRange{{20, 30, "tcp"}})
   277  	c.Assert(err, jc.ErrorIsNil)
   278  	ports, err = inst2.Ports("2")
   279  	c.Assert(err, jc.ErrorIsNil)
   280  	c.Assert(ports, gc.DeepEquals, oldPorts)
   281  
   282  	// Check that opening the same port again and another port is ok.
   283  	err = inst2.OpenPorts("2", []network.PortRange{{45, 45, "tcp"}, {99, 99, "tcp"}})
   284  	c.Assert(err, jc.ErrorIsNil)
   285  	ports, err = inst2.Ports("2")
   286  	c.Assert(err, jc.ErrorIsNil)
   287  	c.Assert(ports, gc.DeepEquals, []network.PortRange{{20, 30, "tcp"}, {45, 45, "tcp"}, {89, 89, "tcp"}, {99, 99, "tcp"}})
   288  
   289  	err = inst2.ClosePorts("2", []network.PortRange{{45, 45, "tcp"}, {99, 99, "tcp"}, {20, 30, "tcp"}})
   290  	c.Assert(err, jc.ErrorIsNil)
   291  
   292  	// Check that we can close ports and that there's no crosstalk.
   293  	ports, err = inst2.Ports("2")
   294  	c.Assert(err, jc.ErrorIsNil)
   295  	c.Assert(ports, gc.DeepEquals, []network.PortRange{{89, 89, "tcp"}})
   296  	ports, err = inst1.Ports("1")
   297  	c.Assert(err, jc.ErrorIsNil)
   298  	c.Assert(ports, gc.DeepEquals, []network.PortRange{{45, 45, "tcp"}, {80, 100, "tcp"}, {67, 67, "udp"}})
   299  
   300  	// Check that we can close multiple ports.
   301  	err = inst1.ClosePorts("1", []network.PortRange{{45, 45, "tcp"}, {67, 67, "udp"}, {80, 100, "tcp"}})
   302  	c.Assert(err, jc.ErrorIsNil)
   303  	ports, err = inst1.Ports("1")
   304  	c.Assert(ports, gc.HasLen, 0)
   305  
   306  	// Check that we can close ports that aren't there.
   307  	err = inst2.ClosePorts("2", []network.PortRange{{111, 111, "tcp"}, {222, 222, "udp"}, {600, 700, "tcp"}})
   308  	c.Assert(err, jc.ErrorIsNil)
   309  	ports, err = inst2.Ports("2")
   310  	c.Assert(ports, gc.DeepEquals, []network.PortRange{{89, 89, "tcp"}})
   311  
   312  	// Check errors when acting on environment.
   313  	err = t.Env.OpenPorts([]network.PortRange{{80, 80, "tcp"}})
   314  	c.Assert(err, gc.ErrorMatches, `invalid firewall mode "instance" for opening ports on environment`)
   315  
   316  	err = t.Env.ClosePorts([]network.PortRange{{80, 80, "tcp"}})
   317  	c.Assert(err, gc.ErrorMatches, `invalid firewall mode "instance" for closing ports on environment`)
   318  
   319  	_, err = t.Env.Ports()
   320  	c.Assert(err, gc.ErrorMatches, `invalid firewall mode "instance" for retrieving ports from environment`)
   321  }
   322  
   323  func (t *LiveTests) TestGlobalPorts(c *gc.C) {
   324  	t.BootstrapOnce(c)
   325  
   326  	// Change configuration.
   327  	oldConfig := t.Env.Config()
   328  	defer func() {
   329  		err := t.Env.SetConfig(oldConfig)
   330  		c.Assert(err, jc.ErrorIsNil)
   331  	}()
   332  
   333  	attrs := t.Env.Config().AllAttrs()
   334  	attrs["firewall-mode"] = config.FwGlobal
   335  	newConfig, err := t.Env.Config().Apply(attrs)
   336  	c.Assert(err, jc.ErrorIsNil)
   337  	err = t.Env.SetConfig(newConfig)
   338  	c.Assert(err, jc.ErrorIsNil)
   339  
   340  	// Create instances and check open ports on both instances.
   341  	inst1, _ := jujutesting.AssertStartInstance(c, t.Env, "1")
   342  	defer t.Env.StopInstances(inst1.Id())
   343  	ports, err := t.Env.Ports()
   344  	c.Assert(err, jc.ErrorIsNil)
   345  	c.Assert(ports, gc.HasLen, 0)
   346  
   347  	inst2, _ := jujutesting.AssertStartInstance(c, t.Env, "2")
   348  	ports, err = t.Env.Ports()
   349  	c.Assert(err, jc.ErrorIsNil)
   350  	c.Assert(ports, gc.HasLen, 0)
   351  	defer t.Env.StopInstances(inst2.Id())
   352  
   353  	err = t.Env.OpenPorts([]network.PortRange{{67, 67, "udp"}, {45, 45, "tcp"}, {89, 89, "tcp"}, {99, 99, "tcp"}, {100, 110, "tcp"}})
   354  	c.Assert(err, jc.ErrorIsNil)
   355  
   356  	ports, err = t.Env.Ports()
   357  	c.Assert(err, jc.ErrorIsNil)
   358  	c.Assert(ports, gc.DeepEquals, []network.PortRange{{45, 45, "tcp"}, {89, 89, "tcp"}, {99, 99, "tcp"}, {100, 110, "tcp"}, {67, 67, "udp"}})
   359  
   360  	// Check closing some ports.
   361  	err = t.Env.ClosePorts([]network.PortRange{{99, 99, "tcp"}, {67, 67, "udp"}})
   362  	c.Assert(err, jc.ErrorIsNil)
   363  
   364  	ports, err = t.Env.Ports()
   365  	c.Assert(err, jc.ErrorIsNil)
   366  	c.Assert(ports, gc.DeepEquals, []network.PortRange{{45, 45, "tcp"}, {89, 89, "tcp"}, {100, 110, "tcp"}})
   367  
   368  	// Check that we can close ports that aren't there.
   369  	err = t.Env.ClosePorts([]network.PortRange{{111, 111, "tcp"}, {222, 222, "udp"}, {2000, 2500, "tcp"}})
   370  	c.Assert(err, jc.ErrorIsNil)
   371  
   372  	ports, err = t.Env.Ports()
   373  	c.Assert(err, jc.ErrorIsNil)
   374  	c.Assert(ports, gc.DeepEquals, []network.PortRange{{45, 45, "tcp"}, {89, 89, "tcp"}, {100, 110, "tcp"}})
   375  
   376  	// Check errors when acting on instances.
   377  	err = inst1.OpenPorts("1", []network.PortRange{{80, 80, "tcp"}})
   378  	c.Assert(err, gc.ErrorMatches, `invalid firewall mode "global" for opening ports on instance`)
   379  
   380  	err = inst1.ClosePorts("1", []network.PortRange{{80, 80, "tcp"}})
   381  	c.Assert(err, gc.ErrorMatches, `invalid firewall mode "global" for closing ports on instance`)
   382  
   383  	_, err = inst1.Ports("1")
   384  	c.Assert(err, gc.ErrorMatches, `invalid firewall mode "global" for retrieving ports from instance`)
   385  }
   386  
   387  func (t *LiveTests) TestBootstrapMultiple(c *gc.C) {
   388  	// bootstrap.Bootstrap no longer raises errors if the environment is
   389  	// already up, this has been moved into the bootstrap command.
   390  	t.BootstrapOnce(c)
   391  
   392  	err := bootstrap.EnsureNotBootstrapped(t.Env)
   393  	c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped")
   394  
   395  	c.Logf("destroy env")
   396  	env := t.Env
   397  	t.Destroy(c)
   398  	err = env.Destroy() // Again, should work fine and do nothing.
   399  	c.Assert(err, jc.ErrorIsNil)
   400  
   401  	// check that we can bootstrap after destroy
   402  	t.BootstrapOnce(c)
   403  }
   404  
   405  func (t *LiveTests) TestBootstrapAndDeploy(c *gc.C) {
   406  	if !t.CanOpenState || !t.HasProvisioner {
   407  		c.Skip(fmt.Sprintf("skipping provisioner test, CanOpenState: %v, HasProvisioner: %v", t.CanOpenState, t.HasProvisioner))
   408  	}
   409  	t.BootstrapOnce(c)
   410  
   411  	// TODO(niemeyer): Stop growing this kitchen sink test and split it into proper parts.
   412  
   413  	c.Logf("opening state")
   414  	st := t.Env.(jujutesting.GetStater).GetStateInAPIServer()
   415  
   416  	env, err := st.Environment()
   417  	c.Assert(err, jc.ErrorIsNil)
   418  	owner := env.Owner()
   419  
   420  	c.Logf("opening API connection")
   421  	apiState, err := juju.NewAPIState(owner, t.Env, api.DefaultDialOpts())
   422  	c.Assert(err, jc.ErrorIsNil)
   423  	defer apiState.Close()
   424  
   425  	// Check that the agent version has made it through the
   426  	// bootstrap process (it's optional in the config.Config)
   427  	cfg, err := st.EnvironConfig()
   428  	c.Assert(err, jc.ErrorIsNil)
   429  	agentVersion, ok := cfg.AgentVersion()
   430  	c.Check(ok, jc.IsTrue)
   431  	c.Check(agentVersion, gc.Equals, version.Current.Number)
   432  
   433  	// Check that the constraints have been set in the environment.
   434  	cons, err := st.EnvironConstraints()
   435  	c.Assert(err, jc.ErrorIsNil)
   436  	c.Assert(cons.String(), gc.Equals, "mem=2048M")
   437  
   438  	// Wait for machine agent to come up on the bootstrap
   439  	// machine and find the deployed series from that.
   440  	m0, err := st.Machine("0")
   441  	c.Assert(err, jc.ErrorIsNil)
   442  
   443  	instId0, err := m0.InstanceId()
   444  	c.Assert(err, jc.ErrorIsNil)
   445  
   446  	// Check that the API connection is working.
   447  	status, err := apiState.Client().Status(nil)
   448  	c.Assert(err, jc.ErrorIsNil)
   449  	c.Assert(status.Machines["0"].InstanceId, gc.Equals, string(instId0))
   450  
   451  	mw0 := newMachineToolWaiter(m0)
   452  	defer mw0.Stop()
   453  
   454  	// If the series has not been specified, we expect the most recent Ubuntu LTS release to be used.
   455  	expectedVersion := version.Current
   456  	expectedVersion.Series = config.LatestLtsSeries()
   457  
   458  	mtools0 := waitAgentTools(c, mw0, expectedVersion)
   459  
   460  	// Create a new service and deploy a unit of it.
   461  	c.Logf("deploying service")
   462  	repoDir := c.MkDir()
   463  	url := testcharms.Repo.ClonedURL(repoDir, mtools0.Version.Series, "dummy")
   464  	sch, err := jujutesting.PutCharm(st, url, &charmrepo.LocalRepository{Path: repoDir}, false)
   465  	c.Assert(err, jc.ErrorIsNil)
   466  	svc, err := st.AddService("dummy", owner.String(), sch, nil, nil)
   467  	c.Assert(err, jc.ErrorIsNil)
   468  	units, err := juju.AddUnits(st, svc, 1, "")
   469  	c.Assert(err, jc.ErrorIsNil)
   470  	unit := units[0]
   471  
   472  	// Wait for the unit's machine and associated agent to come up
   473  	// and announce itself.
   474  	mid1, err := unit.AssignedMachineId()
   475  	c.Assert(err, jc.ErrorIsNil)
   476  	m1, err := st.Machine(mid1)
   477  	c.Assert(err, jc.ErrorIsNil)
   478  	mw1 := newMachineToolWaiter(m1)
   479  	defer mw1.Stop()
   480  	waitAgentTools(c, mw1, mtools0.Version)
   481  
   482  	err = m1.Refresh()
   483  	c.Assert(err, jc.ErrorIsNil)
   484  	instId1, err := m1.InstanceId()
   485  	c.Assert(err, jc.ErrorIsNil)
   486  	uw := newUnitToolWaiter(unit)
   487  	defer uw.Stop()
   488  	utools := waitAgentTools(c, uw, expectedVersion)
   489  
   490  	// Check that we can upgrade the environment.
   491  	newVersion := utools.Version
   492  	newVersion.Patch++
   493  	t.checkUpgrade(c, st, newVersion, mw0, mw1, uw)
   494  
   495  	// BUG(niemeyer): Logic below is very much wrong. Must be:
   496  	//
   497  	// 1. EnsureDying on the unit and EnsureDying on the machine
   498  	// 2. Unit dies by itself
   499  	// 3. Machine removes dead unit
   500  	// 4. Machine dies by itself
   501  	// 5. Provisioner removes dead machine
   502  	//
   503  
   504  	// Now remove the unit and its assigned machine and
   505  	// check that the PA removes it.
   506  	c.Logf("removing unit")
   507  	err = unit.Destroy()
   508  	c.Assert(err, jc.ErrorIsNil)
   509  
   510  	// Wait until unit is dead
   511  	uwatch := unit.Watch()
   512  	defer uwatch.Stop()
   513  	for unit.Life() != state.Dead {
   514  		c.Logf("waiting for unit change")
   515  		<-uwatch.Changes()
   516  		err := unit.Refresh()
   517  		c.Logf("refreshed; err %v", err)
   518  		if errors.IsNotFound(err) {
   519  			c.Logf("unit has been removed")
   520  			break
   521  		}
   522  		c.Assert(err, jc.ErrorIsNil)
   523  	}
   524  	for {
   525  		c.Logf("destroying machine")
   526  		err := m1.Destroy()
   527  		if err == nil {
   528  			break
   529  		}
   530  		c.Assert(err, gc.FitsTypeOf, &state.HasAssignedUnitsError{})
   531  		time.Sleep(5 * time.Second)
   532  		err = m1.Refresh()
   533  		if errors.IsNotFound(err) {
   534  			break
   535  		}
   536  		c.Assert(err, jc.ErrorIsNil)
   537  	}
   538  	c.Logf("waiting for instance to be removed")
   539  	t.assertStopInstance(c, t.Env, instId1)
   540  }
   541  
   542  type tooler interface {
   543  	Life() state.Life
   544  	AgentTools() (*coretools.Tools, error)
   545  	Refresh() error
   546  	String() string
   547  }
   548  
   549  type watcher interface {
   550  	Stop() error
   551  	Err() error
   552  }
   553  
   554  type toolsWaiter struct {
   555  	lastTools *coretools.Tools
   556  	// changes is a chan of struct{} so that it can
   557  	// be used with different kinds of entity watcher.
   558  	changes chan struct{}
   559  	watcher watcher
   560  	tooler  tooler
   561  }
   562  
   563  func newMachineToolWaiter(m *state.Machine) *toolsWaiter {
   564  	w := m.Watch()
   565  	waiter := &toolsWaiter{
   566  		changes: make(chan struct{}, 1),
   567  		watcher: w,
   568  		tooler:  m,
   569  	}
   570  	go func() {
   571  		for _ = range w.Changes() {
   572  			waiter.changes <- struct{}{}
   573  		}
   574  		close(waiter.changes)
   575  	}()
   576  	return waiter
   577  }
   578  
   579  func newUnitToolWaiter(u *state.Unit) *toolsWaiter {
   580  	w := u.Watch()
   581  	waiter := &toolsWaiter{
   582  		changes: make(chan struct{}, 1),
   583  		watcher: w,
   584  		tooler:  u,
   585  	}
   586  	go func() {
   587  		for _ = range w.Changes() {
   588  			waiter.changes <- struct{}{}
   589  		}
   590  		close(waiter.changes)
   591  	}()
   592  	return waiter
   593  }
   594  
   595  func (w *toolsWaiter) Stop() error {
   596  	return w.watcher.Stop()
   597  }
   598  
   599  // NextTools returns the next changed tools, waiting
   600  // until the tools are actually set.
   601  func (w *toolsWaiter) NextTools(c *gc.C) (*coretools.Tools, error) {
   602  	for _ = range w.changes {
   603  		err := w.tooler.Refresh()
   604  		if err != nil {
   605  			return nil, fmt.Errorf("cannot refresh: %v", err)
   606  		}
   607  		if w.tooler.Life() == state.Dead {
   608  			return nil, fmt.Errorf("object is dead")
   609  		}
   610  		tools, err := w.tooler.AgentTools()
   611  		if errors.IsNotFound(err) {
   612  			c.Logf("tools not yet set")
   613  			continue
   614  		}
   615  		if err != nil {
   616  			return nil, err
   617  		}
   618  		changed := w.lastTools == nil || *tools != *w.lastTools
   619  		w.lastTools = tools
   620  		if changed {
   621  			return tools, nil
   622  		}
   623  		c.Logf("found same tools")
   624  	}
   625  	return nil, fmt.Errorf("watcher closed prematurely: %v", w.watcher.Err())
   626  }
   627  
   628  // waitAgentTools waits for the given agent
   629  // to start and returns the tools that it is running.
   630  func waitAgentTools(c *gc.C, w *toolsWaiter, expect version.Binary) *coretools.Tools {
   631  	c.Logf("waiting for %v to signal agent version", w.tooler.String())
   632  	tools, err := w.NextTools(c)
   633  	c.Assert(err, jc.ErrorIsNil)
   634  	c.Check(tools.Version, gc.Equals, expect)
   635  	return tools
   636  }
   637  
   638  // checkUpgrade sets the environment agent version and checks that
   639  // all the provided watchers upgrade to the requested version.
   640  func (t *LiveTests) checkUpgrade(c *gc.C, st *state.State, newVersion version.Binary, waiters ...*toolsWaiter) {
   641  	c.Logf("putting testing version of juju tools")
   642  	upgradeTools, err := sync.Upload(t.toolsStorage, "released", &newVersion.Number, newVersion.Series)
   643  	c.Assert(err, jc.ErrorIsNil)
   644  	// sync.Upload always returns tools for the series on which the tests are running.
   645  	// We are only interested in checking the version.Number below so need to fake the
   646  	// upgraded tools series to match that of newVersion.
   647  	upgradeTools.Version.Series = newVersion.Series
   648  
   649  	// Check that the put version really is the version we expect.
   650  	c.Assert(upgradeTools.Version, gc.Equals, newVersion)
   651  	err = statetesting.SetAgentVersion(st, newVersion.Number)
   652  	c.Assert(err, jc.ErrorIsNil)
   653  
   654  	for i, w := range waiters {
   655  		c.Logf("waiting for upgrade of %d: %v", i, w.tooler.String())
   656  
   657  		waitAgentTools(c, w, newVersion)
   658  		c.Logf("upgrade %d successful", i)
   659  	}
   660  }
   661  
   662  var waitAgent = utils.AttemptStrategy{
   663  	Total: 30 * time.Second,
   664  	Delay: 1 * time.Second,
   665  }
   666  
   667  func (t *LiveTests) assertStartInstance(c *gc.C, m *state.Machine) {
   668  	// Wait for machine to get an instance id.
   669  	for a := waitAgent.Start(); a.Next(); {
   670  		err := m.Refresh()
   671  		c.Assert(err, jc.ErrorIsNil)
   672  		instId, err := m.InstanceId()
   673  		if err != nil {
   674  			c.Assert(err, jc.Satisfies, errors.IsNotProvisioned)
   675  			continue
   676  		}
   677  		_, err = t.Env.Instances([]instance.Id{instId})
   678  		c.Assert(err, jc.ErrorIsNil)
   679  		return
   680  	}
   681  	c.Fatalf("provisioner failed to start machine after %v", waitAgent.Total)
   682  }
   683  
   684  func (t *LiveTests) assertStopInstance(c *gc.C, env environs.Environ, instId instance.Id) {
   685  	var err error
   686  	for a := waitAgent.Start(); a.Next(); {
   687  		_, err = t.Env.Instances([]instance.Id{instId})
   688  		if err == nil {
   689  			continue
   690  		}
   691  		if err == environs.ErrNoInstances {
   692  			return
   693  		}
   694  		c.Logf("error from Instances: %v", err)
   695  	}
   696  	c.Fatalf("provisioner failed to stop machine after %v", waitAgent.Total)
   697  }
   698  
   699  // assertInstanceId asserts that the machine has an instance id
   700  // that matches that of the given instance. If the instance is nil,
   701  // It asserts that the instance id is unset.
   702  func assertInstanceId(c *gc.C, m *state.Machine, inst instance.Instance) {
   703  	var wantId, gotId instance.Id
   704  	var err error
   705  	if inst != nil {
   706  		wantId = inst.Id()
   707  	}
   708  	for a := waitAgent.Start(); a.Next(); {
   709  		err := m.Refresh()
   710  		c.Assert(err, jc.ErrorIsNil)
   711  		gotId, err = m.InstanceId()
   712  		if err != nil {
   713  			c.Assert(err, jc.Satisfies, errors.IsNotProvisioned)
   714  			if inst == nil {
   715  				return
   716  			}
   717  			continue
   718  		}
   719  		break
   720  	}
   721  	c.Assert(err, jc.ErrorIsNil)
   722  	c.Assert(gotId, gc.Equals, wantId)
   723  }
   724  
   725  // Check that we get a consistent error when asking for an instance without
   726  // a valid machine config.
   727  func (t *LiveTests) TestStartInstanceWithEmptyNonceFails(c *gc.C) {
   728  	machineId := "4"
   729  	stateInfo := jujutesting.FakeStateInfo(machineId)
   730  	apiInfo := jujutesting.FakeAPIInfo(machineId)
   731  	instanceConfig, err := instancecfg.NewInstanceConfig(machineId, "", "released", "quantal", true, nil, stateInfo, apiInfo)
   732  	c.Assert(err, jc.ErrorIsNil)
   733  
   734  	t.PrepareOnce(c)
   735  	possibleTools := envtesting.AssertUploadFakeToolsVersions(c, t.toolsStorage, "released", "released", version.MustParseBinary("5.4.5-trusty-amd64"))
   736  	result, err := t.Env.StartInstance(environs.StartInstanceParams{
   737  		Tools:          possibleTools,
   738  		InstanceConfig: instanceConfig,
   739  	})
   740  	if result != nil && result.Instance != nil {
   741  		err := t.Env.StopInstances(result.Instance.Id())
   742  		c.Check(err, jc.ErrorIsNil)
   743  	}
   744  	c.Assert(result, gc.IsNil)
   745  	c.Assert(err, gc.ErrorMatches, ".*missing machine nonce")
   746  }
   747  
   748  func (t *LiveTests) TestBootstrapWithDefaultSeries(c *gc.C) {
   749  	if !t.HasProvisioner {
   750  		c.Skip("HasProvisioner is false; cannot test deployment")
   751  	}
   752  
   753  	current := version.Current
   754  	other := current
   755  	other.Series = "quantal"
   756  	if current == other {
   757  		other.Series = "precise"
   758  	}
   759  
   760  	dummyCfg, err := config.New(config.NoDefaults, dummy.SampleConfig().Merge(coretesting.Attrs{
   761  		"state-server": false,
   762  		"name":         "dummy storage",
   763  	}))
   764  	dummyenv, err := environs.Prepare(dummyCfg, envtesting.BootstrapContext(c), configstore.NewMem())
   765  	c.Assert(err, jc.ErrorIsNil)
   766  	defer dummyenv.Destroy()
   767  
   768  	t.Destroy(c)
   769  
   770  	attrs := t.TestConfig.Merge(coretesting.Attrs{"default-series": other.Series})
   771  	cfg, err := config.New(config.NoDefaults, attrs)
   772  	c.Assert(err, jc.ErrorIsNil)
   773  	env, err := environs.Prepare(cfg, envtesting.BootstrapContext(c), t.ConfigStore)
   774  	c.Assert(err, jc.ErrorIsNil)
   775  	defer environs.Destroy(env, t.ConfigStore)
   776  
   777  	err = bootstrap.Bootstrap(envtesting.BootstrapContext(c), env, bootstrap.BootstrapParams{})
   778  	c.Assert(err, jc.ErrorIsNil)
   779  
   780  	st := t.Env.(jujutesting.GetStater).GetStateInAPIServer()
   781  	// Wait for machine agent to come up on the bootstrap
   782  	// machine and ensure it deployed the proper series.
   783  	m0, err := st.Machine("0")
   784  	c.Assert(err, jc.ErrorIsNil)
   785  	mw0 := newMachineToolWaiter(m0)
   786  	defer mw0.Stop()
   787  
   788  	waitAgentTools(c, mw0, other)
   789  }