launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/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  	"bytes"
     8  	"fmt"
     9  	"io"
    10  	"io/ioutil"
    11  	"strings"
    12  	"time"
    13  
    14  	gc "launchpad.net/gocheck"
    15  
    16  	"launchpad.net/juju-core/charm"
    17  	"launchpad.net/juju-core/constraints"
    18  	"launchpad.net/juju-core/environs"
    19  	"launchpad.net/juju-core/environs/bootstrap"
    20  	"launchpad.net/juju-core/environs/config"
    21  	"launchpad.net/juju-core/environs/configstore"
    22  	"launchpad.net/juju-core/environs/storage"
    23  	"launchpad.net/juju-core/environs/sync"
    24  	envtesting "launchpad.net/juju-core/environs/testing"
    25  	envtools "launchpad.net/juju-core/environs/tools"
    26  	"launchpad.net/juju-core/errors"
    27  	"launchpad.net/juju-core/instance"
    28  	"launchpad.net/juju-core/juju"
    29  	"launchpad.net/juju-core/juju/testing"
    30  	"launchpad.net/juju-core/provider/common"
    31  	"launchpad.net/juju-core/provider/dummy"
    32  	"launchpad.net/juju-core/state"
    33  	"launchpad.net/juju-core/state/api"
    34  	statetesting "launchpad.net/juju-core/state/testing"
    35  	coretesting "launchpad.net/juju-core/testing"
    36  	jc "launchpad.net/juju-core/testing/checkers"
    37  	"launchpad.net/juju-core/testing/testbase"
    38  	coretools "launchpad.net/juju-core/tools"
    39  	"launchpad.net/juju-core/utils"
    40  	"launchpad.net/juju-core/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  	testbase.LoggingSuite
    48  	envtesting.ToolsFixture
    49  
    50  	// TestConfig contains the configuration attributes for opening an environment.
    51  	TestConfig coretesting.Attrs
    52  
    53  	// Attempt holds a strategy for waiting until the environment
    54  	// becomes logically consistent.
    55  	Attempt utils.AttemptStrategy
    56  
    57  	// CanOpenState should be true if the testing environment allows
    58  	// the state to be opened after bootstrapping.
    59  	CanOpenState bool
    60  
    61  	// HasProvisioner should be true if the environment has
    62  	// a provisioning agent.
    63  	HasProvisioner bool
    64  
    65  	// Env holds the currently opened environment.
    66  	// This is set by PrepareOnce and BootstrapOnce.
    67  	Env environs.Environ
    68  
    69  	// ConfigStore holds the configuration storage
    70  	// used when preparing the environment.
    71  	// This is initialized by SetUpSuite.
    72  	ConfigStore configstore.Storage
    73  
    74  	prepared     bool
    75  	bootstrapped bool
    76  }
    77  
    78  func (t *LiveTests) SetUpSuite(c *gc.C) {
    79  	t.LoggingSuite.SetUpSuite(c)
    80  	t.ConfigStore = configstore.NewMem()
    81  }
    82  
    83  func (t *LiveTests) SetUpTest(c *gc.C) {
    84  	t.LoggingSuite.SetUpTest(c)
    85  	t.ToolsFixture.SetUpTest(c)
    86  }
    87  
    88  func publicAttrs(e environs.Environ) map[string]interface{} {
    89  	cfg := e.Config()
    90  	secrets, err := e.Provider().SecretAttrs(cfg)
    91  	if err != nil {
    92  		panic(err)
    93  	}
    94  	attrs := cfg.AllAttrs()
    95  	for attr := range secrets {
    96  		delete(attrs, attr)
    97  	}
    98  	return attrs
    99  }
   100  
   101  func (t *LiveTests) TearDownSuite(c *gc.C) {
   102  	if t.Env != nil {
   103  		t.Destroy(c)
   104  	}
   105  	t.LoggingSuite.TearDownSuite(c)
   106  }
   107  
   108  func (t *LiveTests) TearDownTest(c *gc.C) {
   109  	t.ToolsFixture.TearDownTest(c)
   110  	t.LoggingSuite.TearDownTest(c)
   111  }
   112  
   113  // PrepareOnce ensures that the environment is
   114  // available and prepared. It sets t.Env appropriately.
   115  func (t *LiveTests) PrepareOnce(c *gc.C) {
   116  	if t.prepared {
   117  		return
   118  	}
   119  	cfg, err := config.New(config.NoDefaults, t.TestConfig)
   120  	c.Assert(err, gc.IsNil)
   121  	e, err := environs.Prepare(cfg, t.ConfigStore)
   122  	c.Assert(err, gc.IsNil, gc.Commentf("preparing environ %#v", t.TestConfig))
   123  	c.Assert(e, gc.NotNil)
   124  	t.Env = e
   125  	t.prepared = true
   126  }
   127  
   128  func (t *LiveTests) BootstrapOnce(c *gc.C) {
   129  	if t.bootstrapped {
   130  		return
   131  	}
   132  	t.PrepareOnce(c)
   133  	// We only build and upload tools if there will be a state agent that
   134  	// we could connect to (actual live tests, rather than local-only)
   135  	cons := constraints.MustParse("mem=2G")
   136  	if t.CanOpenState {
   137  		_, err := sync.Upload(t.Env.Storage(), nil, config.DefaultSeries)
   138  		c.Assert(err, gc.IsNil)
   139  	}
   140  	envtesting.UploadFakeTools(c, t.Env.Storage())
   141  	err := common.EnsureNotBootstrapped(t.Env)
   142  	c.Assert(err, gc.IsNil)
   143  	err = bootstrap.Bootstrap(bootstrapContext(c), t.Env, cons)
   144  	c.Assert(err, gc.IsNil)
   145  	t.bootstrapped = true
   146  }
   147  
   148  func (t *LiveTests) Destroy(c *gc.C) {
   149  	if t.Env == nil {
   150  		return
   151  	}
   152  	err := environs.Destroy(t.Env, t.ConfigStore)
   153  	c.Assert(err, gc.IsNil)
   154  	t.bootstrapped = false
   155  	t.prepared = false
   156  	t.Env = nil
   157  }
   158  
   159  func (t *LiveTests) TestPrechecker(c *gc.C) {
   160  	// Providers may implement Prechecker. If they do, then they should
   161  	// return nil for empty constraints (excluding the null provider).
   162  	prechecker, ok := t.Env.(environs.Prechecker)
   163  	if !ok {
   164  		return
   165  	}
   166  
   167  	const series = "precise"
   168  	var cons constraints.Value
   169  	c.Check(prechecker.PrecheckInstance(series, cons), gc.IsNil)
   170  
   171  	err := prechecker.PrecheckContainer(series, instance.LXC)
   172  	// If err is nil, that is fine, some providers support containers.
   173  	if err != nil {
   174  		// But for ones that don't, they should have a standard error format.
   175  		c.Check(err, gc.ErrorMatches, ".*provider does not support .*containers")
   176  		c.Check(err, jc.Satisfies, environs.IsContainersUnsupportedError)
   177  	}
   178  }
   179  
   180  // TestStartStop is similar to Tests.TestStartStop except
   181  // that it does not assume a pristine environment.
   182  func (t *LiveTests) TestStartStop(c *gc.C) {
   183  	t.PrepareOnce(c)
   184  	envtesting.UploadFakeTools(c, t.Env.Storage())
   185  
   186  	inst, _ := testing.AssertStartInstance(c, t.Env, "0")
   187  	c.Assert(inst, gc.NotNil)
   188  	id0 := inst.Id()
   189  
   190  	insts, err := t.Env.Instances([]instance.Id{id0, id0})
   191  	c.Assert(err, gc.IsNil)
   192  	c.Assert(insts, gc.HasLen, 2)
   193  	c.Assert(insts[0].Id(), gc.Equals, id0)
   194  	c.Assert(insts[1].Id(), gc.Equals, id0)
   195  
   196  	// Asserting on the return of AllInstances makes the test fragile,
   197  	// as even comparing the before and after start values can be thrown
   198  	// off if other instances have been created or destroyed in the same
   199  	// time frame. Instead, just check the instance we created exists.
   200  	insts, err = t.Env.AllInstances()
   201  	c.Assert(err, gc.IsNil)
   202  	found := false
   203  	for _, inst := range insts {
   204  		if inst.Id() == id0 {
   205  			c.Assert(found, gc.Equals, false, gc.Commentf("%v", insts))
   206  			found = true
   207  		}
   208  	}
   209  	c.Assert(found, gc.Equals, true, gc.Commentf("expected %v in %v", inst, insts))
   210  
   211  	dns, err := inst.WaitDNSName()
   212  	c.Assert(err, gc.IsNil)
   213  	c.Assert(dns, gc.Not(gc.Equals), "")
   214  
   215  	insts, err = t.Env.Instances([]instance.Id{id0, ""})
   216  	c.Assert(err, gc.Equals, environs.ErrPartialInstances)
   217  	c.Assert(insts, gc.HasLen, 2)
   218  	c.Check(insts[0].Id(), gc.Equals, id0)
   219  	c.Check(insts[1], gc.IsNil)
   220  
   221  	err = t.Env.StopInstances([]instance.Instance{inst})
   222  	c.Assert(err, gc.IsNil)
   223  
   224  	// The machine may not be marked as shutting down
   225  	// immediately. Repeat a few times to ensure we get the error.
   226  	for a := t.Attempt.Start(); a.Next(); {
   227  		insts, err = t.Env.Instances([]instance.Id{id0})
   228  		if err != nil {
   229  			break
   230  		}
   231  	}
   232  	c.Assert(err, gc.Equals, environs.ErrNoInstances)
   233  	c.Assert(insts, gc.HasLen, 0)
   234  }
   235  
   236  func (t *LiveTests) TestPorts(c *gc.C) {
   237  	t.PrepareOnce(c)
   238  	envtesting.UploadFakeTools(c, t.Env.Storage())
   239  
   240  	inst1, _ := testing.AssertStartInstance(c, t.Env, "1")
   241  	c.Assert(inst1, gc.NotNil)
   242  	defer t.Env.StopInstances([]instance.Instance{inst1})
   243  	ports, err := inst1.Ports("1")
   244  	c.Assert(err, gc.IsNil)
   245  	c.Assert(ports, gc.HasLen, 0)
   246  
   247  	inst2, _ := testing.AssertStartInstance(c, t.Env, "2")
   248  	c.Assert(inst2, gc.NotNil)
   249  	ports, err = inst2.Ports("2")
   250  	c.Assert(err, gc.IsNil)
   251  	c.Assert(ports, gc.HasLen, 0)
   252  	defer t.Env.StopInstances([]instance.Instance{inst2})
   253  
   254  	// Open some ports and check they're there.
   255  	err = inst1.OpenPorts("1", []instance.Port{{"udp", 67}, {"tcp", 45}})
   256  	c.Assert(err, gc.IsNil)
   257  	ports, err = inst1.Ports("1")
   258  	c.Assert(err, gc.IsNil)
   259  	c.Assert(ports, gc.DeepEquals, []instance.Port{{"tcp", 45}, {"udp", 67}})
   260  	ports, err = inst2.Ports("2")
   261  	c.Assert(err, gc.IsNil)
   262  	c.Assert(ports, gc.HasLen, 0)
   263  
   264  	err = inst2.OpenPorts("2", []instance.Port{{"tcp", 89}, {"tcp", 45}})
   265  	c.Assert(err, gc.IsNil)
   266  
   267  	// Check there's no crosstalk to another machine
   268  	ports, err = inst2.Ports("2")
   269  	c.Assert(err, gc.IsNil)
   270  	c.Assert(ports, gc.DeepEquals, []instance.Port{{"tcp", 45}, {"tcp", 89}})
   271  	ports, err = inst1.Ports("1")
   272  	c.Assert(err, gc.IsNil)
   273  	c.Assert(ports, gc.DeepEquals, []instance.Port{{"tcp", 45}, {"udp", 67}})
   274  
   275  	// Check that opening the same port again is ok.
   276  	oldPorts, err := inst2.Ports("2")
   277  	c.Assert(err, gc.IsNil)
   278  	err = inst2.OpenPorts("2", []instance.Port{{"tcp", 45}})
   279  	c.Assert(err, gc.IsNil)
   280  	ports, err = inst2.Ports("2")
   281  	c.Assert(err, gc.IsNil)
   282  	c.Assert(ports, gc.DeepEquals, oldPorts)
   283  
   284  	// Check that opening the same port again and another port is ok.
   285  	err = inst2.OpenPorts("2", []instance.Port{{"tcp", 45}, {"tcp", 99}})
   286  	c.Assert(err, gc.IsNil)
   287  	ports, err = inst2.Ports("2")
   288  	c.Assert(err, gc.IsNil)
   289  	c.Assert(ports, gc.DeepEquals, []instance.Port{{"tcp", 45}, {"tcp", 89}, {"tcp", 99}})
   290  
   291  	err = inst2.ClosePorts("2", []instance.Port{{"tcp", 45}, {"tcp", 99}})
   292  	c.Assert(err, gc.IsNil)
   293  
   294  	// Check that we can close ports and that there's no crosstalk.
   295  	ports, err = inst2.Ports("2")
   296  	c.Assert(err, gc.IsNil)
   297  	c.Assert(ports, gc.DeepEquals, []instance.Port{{"tcp", 89}})
   298  	ports, err = inst1.Ports("1")
   299  	c.Assert(err, gc.IsNil)
   300  	c.Assert(ports, gc.DeepEquals, []instance.Port{{"tcp", 45}, {"udp", 67}})
   301  
   302  	// Check that we can close multiple ports.
   303  	err = inst1.ClosePorts("1", []instance.Port{{"tcp", 45}, {"udp", 67}})
   304  	c.Assert(err, gc.IsNil)
   305  	ports, err = inst1.Ports("1")
   306  	c.Assert(ports, gc.HasLen, 0)
   307  
   308  	// Check that we can close ports that aren't there.
   309  	err = inst2.ClosePorts("2", []instance.Port{{"tcp", 111}, {"udp", 222}})
   310  	c.Assert(err, gc.IsNil)
   311  	ports, err = inst2.Ports("2")
   312  	c.Assert(ports, gc.DeepEquals, []instance.Port{{"tcp", 89}})
   313  
   314  	// Check errors when acting on environment.
   315  	err = t.Env.OpenPorts([]instance.Port{{"tcp", 80}})
   316  	c.Assert(err, gc.ErrorMatches, `invalid firewall mode "instance" for opening ports on environment`)
   317  
   318  	err = t.Env.ClosePorts([]instance.Port{{"tcp", 80}})
   319  	c.Assert(err, gc.ErrorMatches, `invalid firewall mode "instance" for closing ports on environment`)
   320  
   321  	_, err = t.Env.Ports()
   322  	c.Assert(err, gc.ErrorMatches, `invalid firewall mode "instance" for retrieving ports from environment`)
   323  }
   324  
   325  func (t *LiveTests) TestGlobalPorts(c *gc.C) {
   326  	t.PrepareOnce(c)
   327  	envtesting.UploadFakeTools(c, t.Env.Storage())
   328  
   329  	// Change configuration.
   330  	oldConfig := t.Env.Config()
   331  	defer func() {
   332  		err := t.Env.SetConfig(oldConfig)
   333  		c.Assert(err, gc.IsNil)
   334  	}()
   335  
   336  	attrs := t.Env.Config().AllAttrs()
   337  	attrs["firewall-mode"] = "global"
   338  	newConfig, err := t.Env.Config().Apply(attrs)
   339  	c.Assert(err, gc.IsNil)
   340  	err = t.Env.SetConfig(newConfig)
   341  	c.Assert(err, gc.IsNil)
   342  
   343  	// Create instances and check open ports on both instances.
   344  	inst1, _ := testing.AssertStartInstance(c, t.Env, "1")
   345  	defer t.Env.StopInstances([]instance.Instance{inst1})
   346  	ports, err := t.Env.Ports()
   347  	c.Assert(err, gc.IsNil)
   348  	c.Assert(ports, gc.HasLen, 0)
   349  
   350  	inst2, _ := testing.AssertStartInstance(c, t.Env, "2")
   351  	ports, err = t.Env.Ports()
   352  	c.Assert(err, gc.IsNil)
   353  	c.Assert(ports, gc.HasLen, 0)
   354  	defer t.Env.StopInstances([]instance.Instance{inst2})
   355  
   356  	err = t.Env.OpenPorts([]instance.Port{{"udp", 67}, {"tcp", 45}, {"tcp", 89}, {"tcp", 99}})
   357  	c.Assert(err, gc.IsNil)
   358  
   359  	ports, err = t.Env.Ports()
   360  	c.Assert(err, gc.IsNil)
   361  	c.Assert(ports, gc.DeepEquals, []instance.Port{{"tcp", 45}, {"tcp", 89}, {"tcp", 99}, {"udp", 67}})
   362  
   363  	// Check closing some ports.
   364  	err = t.Env.ClosePorts([]instance.Port{{"tcp", 99}, {"udp", 67}})
   365  	c.Assert(err, gc.IsNil)
   366  
   367  	ports, err = t.Env.Ports()
   368  	c.Assert(err, gc.IsNil)
   369  	c.Assert(ports, gc.DeepEquals, []instance.Port{{"tcp", 45}, {"tcp", 89}})
   370  
   371  	// Check that we can close ports that aren't there.
   372  	err = t.Env.ClosePorts([]instance.Port{{"tcp", 111}, {"udp", 222}})
   373  	c.Assert(err, gc.IsNil)
   374  
   375  	ports, err = t.Env.Ports()
   376  	c.Assert(err, gc.IsNil)
   377  	c.Assert(ports, gc.DeepEquals, []instance.Port{{"tcp", 45}, {"tcp", 89}})
   378  
   379  	// Check errors when acting on instances.
   380  	err = inst1.OpenPorts("1", []instance.Port{{"tcp", 80}})
   381  	c.Assert(err, gc.ErrorMatches, `invalid firewall mode "global" for opening ports on instance`)
   382  
   383  	err = inst1.ClosePorts("1", []instance.Port{{"tcp", 80}})
   384  	c.Assert(err, gc.ErrorMatches, `invalid firewall mode "global" for closing ports on instance`)
   385  
   386  	_, err = inst1.Ports("1")
   387  	c.Assert(err, gc.ErrorMatches, `invalid firewall mode "global" for retrieving ports from instance`)
   388  }
   389  
   390  func (t *LiveTests) TestBootstrapMultiple(c *gc.C) {
   391  	// bootstrap.Bootstrap no longer raises errors if the environment is
   392  	// already up, this has been moved into the bootstrap command.
   393  	t.BootstrapOnce(c)
   394  
   395  	err := common.EnsureNotBootstrapped(t.Env)
   396  	c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped")
   397  
   398  	c.Logf("destroy env")
   399  	env := t.Env
   400  	t.Destroy(c)
   401  	env.Destroy() // Again, should work fine and do nothing.
   402  
   403  	// check that we can bootstrap after destroy
   404  	t.BootstrapOnce(c)
   405  }
   406  
   407  func (t *LiveTests) TestBootstrapAndDeploy(c *gc.C) {
   408  	if !t.CanOpenState || !t.HasProvisioner {
   409  		c.Skip(fmt.Sprintf("skipping provisioner test, CanOpenState: %v, HasProvisioner: %v", t.CanOpenState, t.HasProvisioner))
   410  	}
   411  	t.BootstrapOnce(c)
   412  
   413  	// TODO(niemeyer): Stop growing this kitchen sink test and split it into proper parts.
   414  
   415  	c.Logf("opening connection")
   416  	conn, err := juju.NewConn(t.Env)
   417  	c.Assert(err, gc.IsNil)
   418  	defer conn.Close()
   419  
   420  	c.Logf("opening API connection")
   421  	apiConn, err := juju.NewAPIConn(t.Env, api.DefaultDialOpts())
   422  	c.Assert(err, gc.IsNil)
   423  	defer conn.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 := conn.State.EnvironConfig()
   428  	c.Assert(err, gc.IsNil)
   429  	agentVersion, ok := cfg.AgentVersion()
   430  	c.Check(ok, gc.Equals, true)
   431  	c.Check(agentVersion, gc.Equals, version.Current.Number)
   432  
   433  	// Check that the constraints have been set in the environment.
   434  	cons, err := conn.State.EnvironConstraints()
   435  	c.Assert(err, gc.IsNil)
   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 := conn.State.Machine("0")
   441  	c.Assert(err, gc.IsNil)
   442  
   443  	instId0, err := m0.InstanceId()
   444  	c.Assert(err, gc.IsNil)
   445  
   446  	// Check that the API connection is working.
   447  	status, err := apiConn.State.Client().Status(nil)
   448  	c.Assert(err, gc.IsNil)
   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.DefaultSeries
   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 := coretesting.Charms.ClonedURL(repoDir, mtools0.Version.Series, "dummy")
   464  	sch, err := conn.PutCharm(url, &charm.LocalRepository{repoDir}, false)
   465  	c.Assert(err, gc.IsNil)
   466  	svc, err := conn.State.AddService("dummy", "user-admin", sch)
   467  	c.Assert(err, gc.IsNil)
   468  	units, err := juju.AddUnits(conn.State, svc, 1, "")
   469  	c.Assert(err, gc.IsNil)
   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, gc.IsNil)
   476  	m1, err := conn.State.Machine(mid1)
   477  	c.Assert(err, gc.IsNil)
   478  	mw1 := newMachineToolWaiter(m1)
   479  	defer mw1.Stop()
   480  	waitAgentTools(c, mw1, mtools0.Version)
   481  
   482  	err = m1.Refresh()
   483  	c.Assert(err, gc.IsNil)
   484  	instId1, err := m1.InstanceId()
   485  	c.Assert(err, gc.IsNil)
   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, conn, 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, gc.IsNil)
   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.IsNotFoundError(err) {
   519  			c.Logf("unit has been removed")
   520  			break
   521  		}
   522  		c.Assert(err, gc.IsNil)
   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.IsNotFoundError(err) {
   534  			break
   535  		}
   536  		c.Assert(err, gc.IsNil)
   537  	}
   538  	c.Logf("waiting for instance to be removed")
   539  	t.assertStopInstance(c, conn.Environ, instId1)
   540  }
   541  
   542  func (t *LiveTests) TestBootstrapVerifyStorage(c *gc.C) {
   543  	// Bootstrap automatically verifies that storage is writable.
   544  	t.BootstrapOnce(c)
   545  	environ := t.Env
   546  	stor := environ.Storage()
   547  	reader, err := storage.Get(stor, "bootstrap-verify")
   548  	c.Assert(err, gc.IsNil)
   549  	defer reader.Close()
   550  	contents, err := ioutil.ReadAll(reader)
   551  	c.Assert(err, gc.IsNil)
   552  	c.Check(string(contents), gc.Equals,
   553  		"juju-core storage writing verified: ok\n")
   554  }
   555  
   556  func restoreBootstrapVerificationFile(c *gc.C, stor storage.Storage) {
   557  	content := "juju-core storage writing verified: ok\n"
   558  	contentReader := strings.NewReader(content)
   559  	err := stor.Put("bootstrap-verify", contentReader,
   560  		int64(len(content)))
   561  	c.Assert(err, gc.IsNil)
   562  }
   563  
   564  func (t *LiveTests) TestCheckEnvironmentOnConnect(c *gc.C) {
   565  	// When new connection is established to a bootstraped environment,
   566  	// it is checked that we are running against a juju-core environment.
   567  	if !t.CanOpenState {
   568  		c.Skip("CanOpenState is false; cannot open state connection")
   569  	}
   570  	t.BootstrapOnce(c)
   571  
   572  	conn, err := juju.NewConn(t.Env)
   573  	c.Assert(err, gc.IsNil)
   574  	conn.Close()
   575  
   576  	apiConn, err := juju.NewAPIConn(t.Env, api.DefaultDialOpts())
   577  	c.Assert(err, gc.IsNil)
   578  	apiConn.Close()
   579  }
   580  
   581  func (t *LiveTests) TestCheckEnvironmentOnConnectNoVerificationFile(c *gc.C) {
   582  	// When new connection is established to a bootstraped environment,
   583  	// it is checked that we are running against a juju-core environment.
   584  	//
   585  	// Absence of a verification file means it is a juju-core environment
   586  	// with an older version, which is fine.
   587  	if !t.CanOpenState {
   588  		c.Skip("CanOpenState is false; cannot open state connection")
   589  	}
   590  	t.BootstrapOnce(c)
   591  	environ := t.Env
   592  	stor := environ.Storage()
   593  	err := stor.Remove("bootstrap-verify")
   594  	c.Assert(err, gc.IsNil)
   595  	defer restoreBootstrapVerificationFile(c, stor)
   596  
   597  	conn, err := juju.NewConn(t.Env)
   598  	c.Assert(err, gc.IsNil)
   599  	conn.Close()
   600  }
   601  
   602  func (t *LiveTests) TestCheckEnvironmentOnConnectBadVerificationFile(c *gc.C) {
   603  	// When new connection is established to a bootstraped environment,
   604  	// it is checked that we are running against a juju-core environment.
   605  	//
   606  	// If the verification file has unexpected content, it is not
   607  	// a juju-core environment (likely to a Python juju environment).
   608  	if !t.CanOpenState {
   609  		c.Skip("CanOpenState is false; cannot open state connection")
   610  	}
   611  	t.BootstrapOnce(c)
   612  	environ := t.Env
   613  	stor := environ.Storage()
   614  
   615  	// Finally, replace the content with an arbitrary string.
   616  	badVerificationContent := "bootstrap storage verification"
   617  	reader := strings.NewReader(badVerificationContent)
   618  	err := stor.Put(
   619  		"bootstrap-verify",
   620  		reader,
   621  		int64(len(badVerificationContent)))
   622  	c.Assert(err, gc.IsNil)
   623  	defer restoreBootstrapVerificationFile(c, stor)
   624  
   625  	// Running NewConn() should fail.
   626  	_, err = juju.NewConn(t.Env)
   627  	c.Assert(err, gc.Equals, environs.InvalidEnvironmentError)
   628  }
   629  
   630  type tooler interface {
   631  	Life() state.Life
   632  	AgentTools() (*coretools.Tools, error)
   633  	Refresh() error
   634  	String() string
   635  }
   636  
   637  type watcher interface {
   638  	Stop() error
   639  	Err() error
   640  }
   641  
   642  type toolsWaiter struct {
   643  	lastTools *coretools.Tools
   644  	// changes is a chan of struct{} so that it can
   645  	// be used with different kinds of entity watcher.
   646  	changes chan struct{}
   647  	watcher watcher
   648  	tooler  tooler
   649  }
   650  
   651  func newMachineToolWaiter(m *state.Machine) *toolsWaiter {
   652  	w := m.Watch()
   653  	waiter := &toolsWaiter{
   654  		changes: make(chan struct{}, 1),
   655  		watcher: w,
   656  		tooler:  m,
   657  	}
   658  	go func() {
   659  		for _ = range w.Changes() {
   660  			waiter.changes <- struct{}{}
   661  		}
   662  		close(waiter.changes)
   663  	}()
   664  	return waiter
   665  }
   666  
   667  func newUnitToolWaiter(u *state.Unit) *toolsWaiter {
   668  	w := u.Watch()
   669  	waiter := &toolsWaiter{
   670  		changes: make(chan struct{}, 1),
   671  		watcher: w,
   672  		tooler:  u,
   673  	}
   674  	go func() {
   675  		for _ = range w.Changes() {
   676  			waiter.changes <- struct{}{}
   677  		}
   678  		close(waiter.changes)
   679  	}()
   680  	return waiter
   681  }
   682  
   683  func (w *toolsWaiter) Stop() error {
   684  	return w.watcher.Stop()
   685  }
   686  
   687  // NextTools returns the next changed tools, waiting
   688  // until the tools are actually set.
   689  func (w *toolsWaiter) NextTools(c *gc.C) (*coretools.Tools, error) {
   690  	for _ = range w.changes {
   691  		err := w.tooler.Refresh()
   692  		if err != nil {
   693  			return nil, fmt.Errorf("cannot refresh: %v", err)
   694  		}
   695  		if w.tooler.Life() == state.Dead {
   696  			return nil, fmt.Errorf("object is dead")
   697  		}
   698  		tools, err := w.tooler.AgentTools()
   699  		if errors.IsNotFoundError(err) {
   700  			c.Logf("tools not yet set")
   701  			continue
   702  		}
   703  		if err != nil {
   704  			return nil, err
   705  		}
   706  		changed := w.lastTools == nil || *tools != *w.lastTools
   707  		w.lastTools = tools
   708  		if changed {
   709  			return tools, nil
   710  		}
   711  		c.Logf("found same tools")
   712  	}
   713  	return nil, fmt.Errorf("watcher closed prematurely: %v", w.watcher.Err())
   714  }
   715  
   716  // waitAgentTools waits for the given agent
   717  // to start and returns the tools that it is running.
   718  func waitAgentTools(c *gc.C, w *toolsWaiter, expect version.Binary) *coretools.Tools {
   719  	c.Logf("waiting for %v to signal agent version", w.tooler.String())
   720  	tools, err := w.NextTools(c)
   721  	c.Assert(err, gc.IsNil)
   722  	c.Check(tools.Version, gc.Equals, expect)
   723  	return tools
   724  }
   725  
   726  // checkUpgrade sets the environment agent version and checks that
   727  // all the provided watchers upgrade to the requested version.
   728  func (t *LiveTests) checkUpgrade(c *gc.C, conn *juju.Conn, newVersion version.Binary, waiters ...*toolsWaiter) {
   729  	c.Logf("putting testing version of juju tools")
   730  	upgradeTools, err := sync.Upload(t.Env.Storage(), &newVersion.Number, newVersion.Series)
   731  	c.Assert(err, gc.IsNil)
   732  	// sync.Upload always returns tools for the series on which the tests are running.
   733  	// We are only interested in checking the version.Number below so need to fake the
   734  	// upgraded tools series to match that of newVersion.
   735  	upgradeTools.Version.Series = newVersion.Series
   736  
   737  	// Check that the put version really is the version we expect.
   738  	c.Assert(upgradeTools.Version, gc.Equals, newVersion)
   739  	err = statetesting.SetAgentVersion(conn.State, newVersion.Number)
   740  	c.Assert(err, gc.IsNil)
   741  
   742  	for i, w := range waiters {
   743  		c.Logf("waiting for upgrade of %d: %v", i, w.tooler.String())
   744  
   745  		waitAgentTools(c, w, newVersion)
   746  		c.Logf("upgrade %d successful", i)
   747  	}
   748  }
   749  
   750  var waitAgent = utils.AttemptStrategy{
   751  	Total: 30 * time.Second,
   752  	Delay: 1 * time.Second,
   753  }
   754  
   755  func (t *LiveTests) assertStartInstance(c *gc.C, m *state.Machine) {
   756  	// Wait for machine to get an instance id.
   757  	for a := waitAgent.Start(); a.Next(); {
   758  		err := m.Refresh()
   759  		c.Assert(err, gc.IsNil)
   760  		instId, err := m.InstanceId()
   761  		if err != nil {
   762  			c.Assert(err, jc.Satisfies, state.IsNotProvisionedError)
   763  			continue
   764  		}
   765  		_, err = t.Env.Instances([]instance.Id{instId})
   766  		c.Assert(err, gc.IsNil)
   767  		return
   768  	}
   769  	c.Fatalf("provisioner failed to start machine after %v", waitAgent.Total)
   770  }
   771  
   772  func (t *LiveTests) assertStopInstance(c *gc.C, env environs.Environ, instId instance.Id) {
   773  	var err error
   774  	for a := waitAgent.Start(); a.Next(); {
   775  		_, err = t.Env.Instances([]instance.Id{instId})
   776  		if err == nil {
   777  			continue
   778  		}
   779  		if err == environs.ErrNoInstances {
   780  			return
   781  		}
   782  		c.Logf("error from Instances: %v", err)
   783  	}
   784  	c.Fatalf("provisioner failed to stop machine after %v", waitAgent.Total)
   785  }
   786  
   787  // assertInstanceId asserts that the machine has an instance id
   788  // that matches that of the given instance. If the instance is nil,
   789  // It asserts that the instance id is unset.
   790  func assertInstanceId(c *gc.C, m *state.Machine, inst instance.Instance) {
   791  	var wantId, gotId instance.Id
   792  	var err error
   793  	if inst != nil {
   794  		wantId = inst.Id()
   795  	}
   796  	for a := waitAgent.Start(); a.Next(); {
   797  		err := m.Refresh()
   798  		c.Assert(err, gc.IsNil)
   799  		gotId, err = m.InstanceId()
   800  		if err != nil {
   801  			c.Assert(err, jc.Satisfies, state.IsNotProvisionedError)
   802  			if inst == nil {
   803  				return
   804  			}
   805  			continue
   806  		}
   807  		break
   808  	}
   809  	c.Assert(err, gc.IsNil)
   810  	c.Assert(gotId, gc.Equals, wantId)
   811  }
   812  
   813  // TODO check that binary data works ok?
   814  var contents = []byte("hello\n")
   815  var contents2 = []byte("goodbye\n\n")
   816  
   817  func (t *LiveTests) TestFile(c *gc.C) {
   818  	t.PrepareOnce(c)
   819  	name := fmt.Sprint("testfile", time.Now().UnixNano())
   820  	stor := t.Env.Storage()
   821  
   822  	checkFileDoesNotExist(c, stor, name, t.Attempt)
   823  	checkPutFile(c, stor, name, contents)
   824  	checkFileHasContents(c, stor, name, contents, t.Attempt)
   825  	checkPutFile(c, stor, name, contents2) // check that we can overwrite the file
   826  	checkFileHasContents(c, stor, name, contents2, t.Attempt)
   827  
   828  	// check that the listed contents include the
   829  	// expected name.
   830  	found := false
   831  	var names []string
   832  attempt:
   833  	for a := t.Attempt.Start(); a.Next(); {
   834  		var err error
   835  		names, err = stor.List("")
   836  		c.Assert(err, gc.IsNil)
   837  		for _, lname := range names {
   838  			if lname == name {
   839  				found = true
   840  				break attempt
   841  			}
   842  		}
   843  	}
   844  	if !found {
   845  		c.Errorf("file name %q not found in file list %q", name, names)
   846  	}
   847  	err := stor.Remove(name)
   848  	c.Check(err, gc.IsNil)
   849  	checkFileDoesNotExist(c, stor, name, t.Attempt)
   850  	// removing a file that does not exist should not be an error.
   851  	err = stor.Remove(name)
   852  	c.Check(err, gc.IsNil)
   853  
   854  	// RemoveAll deletes all files from storage.
   855  	checkPutFile(c, stor, "file-1.txt", contents)
   856  	checkPutFile(c, stor, "file-2.txt", contents)
   857  	err = stor.RemoveAll()
   858  	c.Check(err, gc.IsNil)
   859  	checkFileDoesNotExist(c, stor, "file-1.txt", t.Attempt)
   860  	checkFileDoesNotExist(c, stor, "file-2.txt", t.Attempt)
   861  }
   862  
   863  // Check that we get a consistent error when asking for an instance without
   864  // a valid machine config.
   865  func (t *LiveTests) TestStartInstanceWithEmptyNonceFails(c *gc.C) {
   866  	machineId := "4"
   867  	stateInfo := testing.FakeStateInfo(machineId)
   868  	apiInfo := testing.FakeAPIInfo(machineId)
   869  	machineConfig := environs.NewMachineConfig(machineId, "", stateInfo, apiInfo)
   870  
   871  	t.PrepareOnce(c)
   872  	possibleTools := envtesting.AssertUploadFakeToolsVersions(c, t.Env.Storage(), version.MustParseBinary("5.4.5-precise-amd64"))
   873  	inst, _, err := t.Env.StartInstance(constraints.Value{}, possibleTools, machineConfig)
   874  	if inst != nil {
   875  		err := t.Env.StopInstances([]instance.Instance{inst})
   876  		c.Check(err, gc.IsNil)
   877  	}
   878  	c.Assert(inst, gc.IsNil)
   879  	c.Assert(err, gc.ErrorMatches, ".*missing machine nonce")
   880  }
   881  
   882  func (t *LiveTests) TestBootstrapWithDefaultSeries(c *gc.C) {
   883  	if !t.HasProvisioner {
   884  		c.Skip("HasProvisioner is false; cannot test deployment")
   885  	}
   886  
   887  	current := version.Current
   888  	other := current
   889  	other.Series = "quantal"
   890  	if current == other {
   891  		other.Series = "precise"
   892  	}
   893  
   894  	dummyCfg, err := config.New(config.NoDefaults, dummy.SampleConfig().Merge(coretesting.Attrs{
   895  		"state-server": false,
   896  		"name":         "dummy storage",
   897  	}))
   898  	dummyenv, err := environs.Prepare(dummyCfg, configstore.NewMem())
   899  	c.Assert(err, gc.IsNil)
   900  	defer dummyenv.Destroy()
   901  
   902  	t.Destroy(c)
   903  
   904  	attrs := t.TestConfig.Merge(coretesting.Attrs{"default-series": other.Series})
   905  	cfg, err := config.New(config.NoDefaults, attrs)
   906  	c.Assert(err, gc.IsNil)
   907  	env, err := environs.Prepare(cfg, t.ConfigStore)
   908  	c.Assert(err, gc.IsNil)
   909  	defer environs.Destroy(env, t.ConfigStore)
   910  
   911  	currentName := envtools.StorageName(current)
   912  	otherName := envtools.StorageName(other)
   913  	envStorage := env.Storage()
   914  	dummyStorage := dummyenv.Storage()
   915  
   916  	defer envStorage.Remove(otherName)
   917  
   918  	_, err = sync.Upload(dummyStorage, &current.Number)
   919  	c.Assert(err, gc.IsNil)
   920  
   921  	// This will only work while cross-compiling across releases is safe,
   922  	// which depends on external elements. Tends to be safe for the last
   923  	// few releases, but we may have to refactor some day.
   924  	err = storageCopy(dummyStorage, currentName, envStorage, otherName)
   925  	c.Assert(err, gc.IsNil)
   926  
   927  	err = bootstrap.Bootstrap(bootstrapContext(c), env, constraints.Value{})
   928  	c.Assert(err, gc.IsNil)
   929  
   930  	conn, err := juju.NewConn(env)
   931  	c.Assert(err, gc.IsNil)
   932  	defer conn.Close()
   933  
   934  	// Wait for machine agent to come up on the bootstrap
   935  	// machine and ensure it deployed the proper series.
   936  	m0, err := conn.State.Machine("0")
   937  	c.Assert(err, gc.IsNil)
   938  	mw0 := newMachineToolWaiter(m0)
   939  	defer mw0.Stop()
   940  
   941  	waitAgentTools(c, mw0, other)
   942  }
   943  
   944  func storageCopy(source storage.Storage, sourcePath string, target storage.Storage, targetPath string) error {
   945  	rc, err := storage.Get(source, sourcePath)
   946  	if err != nil {
   947  		return err
   948  	}
   949  	var buf bytes.Buffer
   950  	_, err = io.Copy(&buf, rc)
   951  	rc.Close()
   952  	if err != nil {
   953  		return err
   954  	}
   955  	return target.Put(targetPath, &buf, int64(buf.Len()))
   956  }