github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/cmd/jujud/agent/machine_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package agent
     5  
     6  import (
     7  	"io"
     8  	"io/ioutil"
     9  	"os"
    10  	"path/filepath"
    11  	"reflect"
    12  	"runtime"
    13  	"strings"
    14  	"sync/atomic"
    15  	"testing"
    16  	"time"
    17  
    18  	"github.com/juju/cmd"
    19  	"github.com/juju/errors"
    20  	"github.com/juju/names"
    21  	gitjujutesting "github.com/juju/testing"
    22  	jc "github.com/juju/testing/checkers"
    23  	"github.com/juju/utils/clock"
    24  	"github.com/juju/utils/proxy"
    25  	"github.com/juju/utils/set"
    26  	"github.com/juju/utils/symlink"
    27  	gc "gopkg.in/check.v1"
    28  	"gopkg.in/juju/charm.v6-unstable"
    29  	"gopkg.in/juju/charmrepo.v1"
    30  	"gopkg.in/natefinch/lumberjack.v2"
    31  
    32  	"github.com/juju/juju/agent"
    33  	"github.com/juju/juju/api"
    34  	apiaddresser "github.com/juju/juju/api/addresser"
    35  	apideployer "github.com/juju/juju/api/deployer"
    36  	apienvironment "github.com/juju/juju/api/environment"
    37  	apifirewaller "github.com/juju/juju/api/firewaller"
    38  	"github.com/juju/juju/api/imagemetadata"
    39  	apiinstancepoller "github.com/juju/juju/api/instancepoller"
    40  	apimetricsmanager "github.com/juju/juju/api/metricsmanager"
    41  	apinetworker "github.com/juju/juju/api/networker"
    42  	apirsyslog "github.com/juju/juju/api/rsyslog"
    43  	charmtesting "github.com/juju/juju/apiserver/charmrevisionupdater/testing"
    44  	"github.com/juju/juju/apiserver/params"
    45  	"github.com/juju/juju/cert"
    46  	agenttesting "github.com/juju/juju/cmd/jujud/agent/testing"
    47  	cmdutil "github.com/juju/juju/cmd/jujud/util"
    48  	lxctesting "github.com/juju/juju/container/lxc/testing"
    49  	"github.com/juju/juju/environs/config"
    50  	envtesting "github.com/juju/juju/environs/testing"
    51  	"github.com/juju/juju/feature"
    52  	"github.com/juju/juju/instance"
    53  	"github.com/juju/juju/juju"
    54  	jujutesting "github.com/juju/juju/juju/testing"
    55  	"github.com/juju/juju/mongo"
    56  	"github.com/juju/juju/network"
    57  	"github.com/juju/juju/provider/dummy"
    58  	"github.com/juju/juju/service/upstart"
    59  	"github.com/juju/juju/state"
    60  	"github.com/juju/juju/state/watcher"
    61  	"github.com/juju/juju/storage"
    62  	coretesting "github.com/juju/juju/testing"
    63  	"github.com/juju/juju/testing/factory"
    64  	"github.com/juju/juju/tools"
    65  	"github.com/juju/juju/utils/ssh"
    66  	sshtesting "github.com/juju/juju/utils/ssh/testing"
    67  	"github.com/juju/juju/version"
    68  	"github.com/juju/juju/worker"
    69  	"github.com/juju/juju/worker/addresser"
    70  	"github.com/juju/juju/worker/apicaller"
    71  	"github.com/juju/juju/worker/authenticationworker"
    72  	"github.com/juju/juju/worker/certupdater"
    73  	"github.com/juju/juju/worker/deployer"
    74  	"github.com/juju/juju/worker/diskmanager"
    75  	"github.com/juju/juju/worker/instancepoller"
    76  	"github.com/juju/juju/worker/logsender"
    77  	"github.com/juju/juju/worker/machiner"
    78  	"github.com/juju/juju/worker/networker"
    79  	"github.com/juju/juju/worker/peergrouper"
    80  	"github.com/juju/juju/worker/proxyupdater"
    81  	"github.com/juju/juju/worker/resumer"
    82  	"github.com/juju/juju/worker/rsyslog"
    83  	"github.com/juju/juju/worker/singular"
    84  	"github.com/juju/juju/worker/storageprovisioner"
    85  	"github.com/juju/juju/worker/upgrader"
    86  )
    87  
    88  var (
    89  	_ = gc.Suite(&MachineSuite{})
    90  	_ = gc.Suite(&MachineWithCharmsSuite{})
    91  	_ = gc.Suite(&mongoSuite{})
    92  )
    93  
    94  func TestPackage(t *testing.T) {
    95  	// TODO(waigani) 2014-03-19 bug 1294458
    96  	// Refactor to use base suites
    97  
    98  	// Change the path to "juju-run", so that the
    99  	// tests don't try to write to /usr/local/bin.
   100  	JujuRun = mktemp("juju-run", "")
   101  	defer os.Remove(JujuRun)
   102  
   103  	coretesting.MgoTestPackage(t)
   104  }
   105  
   106  type commonMachineSuite struct {
   107  	singularRecord *singularRunnerRecord
   108  	lxctesting.TestSuite
   109  	fakeEnsureMongo *agenttesting.FakeEnsureMongo
   110  	AgentSuite
   111  }
   112  
   113  func (s *commonMachineSuite) SetUpSuite(c *gc.C) {
   114  	s.AgentSuite.SetUpSuite(c)
   115  	s.TestSuite.SetUpSuite(c)
   116  }
   117  
   118  func (s *commonMachineSuite) TearDownSuite(c *gc.C) {
   119  	s.TestSuite.TearDownSuite(c)
   120  	s.AgentSuite.TearDownSuite(c)
   121  }
   122  
   123  func (s *commonMachineSuite) SetUpTest(c *gc.C) {
   124  	s.AgentSuite.PatchValue(&version.Current.Number, coretesting.FakeVersionNumber)
   125  	s.AgentSuite.SetUpTest(c)
   126  	s.TestSuite.SetUpTest(c)
   127  	s.AgentSuite.PatchValue(&charmrepo.CacheDir, c.MkDir())
   128  	s.AgentSuite.PatchValue(&stateWorkerDialOpts, mongo.DefaultDialOpts())
   129  
   130  	os.Remove(JujuRun) // ignore error; may not exist
   131  	// Patch ssh user to avoid touching ~ubuntu/.ssh/authorized_keys.
   132  	s.AgentSuite.PatchValue(&authenticationworker.SSHUser, "")
   133  
   134  	testpath := c.MkDir()
   135  	s.AgentSuite.PatchEnvPathPrepend(testpath)
   136  	// mock out the start method so we can fake install services without sudo
   137  	fakeCmd(filepath.Join(testpath, "start"))
   138  	fakeCmd(filepath.Join(testpath, "stop"))
   139  
   140  	s.AgentSuite.PatchValue(&upstart.InitDir, c.MkDir())
   141  
   142  	s.singularRecord = newSingularRunnerRecord()
   143  	s.AgentSuite.PatchValue(&newSingularRunner, s.singularRecord.newSingularRunner)
   144  	s.AgentSuite.PatchValue(&peergrouperNew, func(st *state.State) (worker.Worker, error) {
   145  		return newDummyWorker(), nil
   146  	})
   147  
   148  	s.fakeEnsureMongo = agenttesting.InstallFakeEnsureMongo(s)
   149  	s.AgentSuite.PatchValue(&maybeInitiateMongoServer, s.fakeEnsureMongo.InitiateMongo)
   150  }
   151  
   152  func fakeCmd(path string) {
   153  	err := ioutil.WriteFile(path, []byte("#!/bin/bash --norc\nexit 0"), 0755)
   154  	if err != nil {
   155  		panic(err)
   156  	}
   157  }
   158  
   159  func (s *commonMachineSuite) TearDownTest(c *gc.C) {
   160  	s.TestSuite.TearDownTest(c)
   161  	s.AgentSuite.TearDownTest(c)
   162  }
   163  
   164  // primeAgent adds a new Machine to run the given jobs, and sets up the
   165  // machine agent's directory.  It returns the new machine, the
   166  // agent's configuration and the tools currently running.
   167  func (s *commonMachineSuite) primeAgent(
   168  	c *gc.C, vers version.Binary,
   169  	jobs ...state.MachineJob) (m *state.Machine, agentConfig agent.ConfigSetterWriter, tools *tools.Tools) {
   170  
   171  	m, err := s.State.AddMachine("quantal", jobs...)
   172  	c.Assert(err, jc.ErrorIsNil)
   173  
   174  	pinger, err := m.SetAgentPresence()
   175  	c.Assert(err, jc.ErrorIsNil)
   176  	s.AddCleanup(func(c *gc.C) {
   177  		err := pinger.Stop()
   178  		c.Check(err, jc.ErrorIsNil)
   179  	})
   180  
   181  	return s.configureMachine(c, m.Id(), vers)
   182  }
   183  
   184  func (s *commonMachineSuite) configureMachine(c *gc.C, machineId string, vers version.Binary) (
   185  	machine *state.Machine, agentConfig agent.ConfigSetterWriter, tools *tools.Tools,
   186  ) {
   187  	m, err := s.State.Machine(machineId)
   188  	c.Assert(err, jc.ErrorIsNil)
   189  
   190  	// Add a machine and ensure it is provisioned.
   191  	inst, md := jujutesting.AssertStartInstance(c, s.Environ, machineId)
   192  	c.Assert(m.SetProvisioned(inst.Id(), agent.BootstrapNonce, md), jc.ErrorIsNil)
   193  
   194  	// Add an address for the tests in case the maybeInitiateMongoServer
   195  	// codepath is exercised.
   196  	s.setFakeMachineAddresses(c, m)
   197  
   198  	// Set up the new machine.
   199  	err = m.SetAgentVersion(vers)
   200  	c.Assert(err, jc.ErrorIsNil)
   201  	err = m.SetPassword(initialMachinePassword)
   202  	c.Assert(err, jc.ErrorIsNil)
   203  	tag := m.Tag()
   204  	if m.IsManager() {
   205  		err = m.SetMongoPassword(initialMachinePassword)
   206  		c.Assert(err, jc.ErrorIsNil)
   207  		agentConfig, tools = s.AgentSuite.PrimeStateAgent(c, tag, initialMachinePassword, vers)
   208  		info, ok := agentConfig.StateServingInfo()
   209  		c.Assert(ok, jc.IsTrue)
   210  		ssi := cmdutil.ParamsStateServingInfoToStateStateServingInfo(info)
   211  		err = s.State.SetStateServingInfo(ssi)
   212  		c.Assert(err, jc.ErrorIsNil)
   213  	} else {
   214  		agentConfig, tools = s.PrimeAgent(c, tag, initialMachinePassword, vers)
   215  	}
   216  	err = agentConfig.Write()
   217  	c.Assert(err, jc.ErrorIsNil)
   218  	return m, agentConfig, tools
   219  }
   220  
   221  // newAgent returns a new MachineAgent instance
   222  func (s *commonMachineSuite) newAgent(c *gc.C, m *state.Machine) *MachineAgent {
   223  	agentConf := agentConf{dataDir: s.DataDir()}
   224  	agentConf.ReadConfig(names.NewMachineTag(m.Id()).String())
   225  	logsCh, err := logsender.InstallBufferedLogWriter(1024)
   226  	c.Assert(err, jc.ErrorIsNil)
   227  	machineAgentFactory := MachineAgentFactoryFn(
   228  		&agentConf, logsCh, &mockLoopDeviceManager{},
   229  	)
   230  	return machineAgentFactory(m.Id())
   231  }
   232  
   233  func (s *MachineSuite) TestParseSuccess(c *gc.C) {
   234  	create := func() (cmd.Command, AgentConf) {
   235  		agentConf := agentConf{dataDir: s.DataDir()}
   236  		a := NewMachineAgentCmd(
   237  			nil,
   238  			MachineAgentFactoryFn(
   239  				&agentConf, nil, &mockLoopDeviceManager{},
   240  			),
   241  			&agentConf,
   242  			&agentConf,
   243  		)
   244  		a.(*machineAgentCmd).logToStdErr = true
   245  
   246  		return a, &agentConf
   247  	}
   248  	a := CheckAgentCommand(c, create, []string{"--machine-id", "42"})
   249  	c.Assert(a.(*machineAgentCmd).machineId, gc.Equals, "42")
   250  }
   251  
   252  type MachineSuite struct {
   253  	commonMachineSuite
   254  	metricAPI *mockMetricAPI
   255  }
   256  
   257  var perEnvSingularWorkers = []string{
   258  	"cleaner",
   259  	"minunitsworker",
   260  	"addresserworker",
   261  	"environ-provisioner",
   262  	"charm-revision-updater",
   263  	"instancepoller",
   264  	"firewaller",
   265  }
   266  
   267  const initialMachinePassword = "machine-password-1234567890"
   268  
   269  func (s *MachineSuite) SetUpTest(c *gc.C) {
   270  	s.commonMachineSuite.SetUpTest(c)
   271  	s.metricAPI = newMockMetricAPI()
   272  	s.PatchValue(&getMetricAPI, func(_ api.Connection) apimetricsmanager.MetricsManagerClient {
   273  		return s.metricAPI
   274  	})
   275  	s.AddCleanup(func(*gc.C) { s.metricAPI.Stop() })
   276  	// Most of these tests normally finish sub-second on a fast machine.
   277  	// If any given test hits a minute, we have almost certainly become
   278  	// wedged, so dump the logs.
   279  	coretesting.DumpTestLogsAfter(time.Minute, c, s)
   280  }
   281  
   282  func (s *MachineSuite) TestParseNonsense(c *gc.C) {
   283  	for _, args := range [][]string{
   284  		{},
   285  		{"--machine-id", "-4004"},
   286  	} {
   287  		var agentConf agentConf
   288  		err := ParseAgentCommand(&machineAgentCmd{agentInitializer: &agentConf}, args)
   289  		c.Assert(err, gc.ErrorMatches, "--machine-id option must be set, and expects a non-negative integer")
   290  	}
   291  }
   292  
   293  func (s *MachineSuite) TestParseUnknown(c *gc.C) {
   294  	var agentConf agentConf
   295  	a := &machineAgentCmd{agentInitializer: &agentConf}
   296  	err := ParseAgentCommand(a, []string{"--machine-id", "42", "blistering barnacles"})
   297  	c.Assert(err, gc.ErrorMatches, `unrecognized args: \["blistering barnacles"\]`)
   298  }
   299  
   300  func (s *MachineSuite) TestRunInvalidMachineId(c *gc.C) {
   301  	c.Skip("agents don't yet distinguish between temporary and permanent errors")
   302  	m, _, _ := s.primeAgent(c, version.Current, state.JobHostUnits)
   303  	err := s.newAgent(c, m).Run(nil)
   304  	c.Assert(err, gc.ErrorMatches, "some error")
   305  }
   306  
   307  func (s *MachineSuite) TestUseLumberjack(c *gc.C) {
   308  	ctx, err := cmd.DefaultContext()
   309  	c.Assert(err, gc.IsNil)
   310  
   311  	agentConf := FakeAgentConfig{}
   312  
   313  	a := NewMachineAgentCmd(
   314  		ctx,
   315  		MachineAgentFactoryFn(
   316  			agentConf, nil, &mockLoopDeviceManager{},
   317  		),
   318  		agentConf,
   319  		agentConf,
   320  	)
   321  	// little hack to set the data that Init expects to already be set
   322  	a.(*machineAgentCmd).machineId = "42"
   323  
   324  	err = a.Init(nil)
   325  	c.Assert(err, gc.IsNil)
   326  
   327  	l, ok := ctx.Stderr.(*lumberjack.Logger)
   328  	c.Assert(ok, jc.IsTrue)
   329  	c.Check(l.MaxAge, gc.Equals, 0)
   330  	c.Check(l.MaxBackups, gc.Equals, 2)
   331  	c.Check(l.Filename, gc.Equals, filepath.FromSlash("/var/log/juju/machine-42.log"))
   332  	c.Check(l.MaxSize, gc.Equals, 300)
   333  }
   334  
   335  func (s *MachineSuite) TestDontUseLumberjack(c *gc.C) {
   336  	ctx, err := cmd.DefaultContext()
   337  	c.Assert(err, gc.IsNil)
   338  
   339  	agentConf := FakeAgentConfig{}
   340  
   341  	a := NewMachineAgentCmd(
   342  		ctx,
   343  		MachineAgentFactoryFn(
   344  			agentConf, nil,
   345  			&mockLoopDeviceManager{},
   346  		),
   347  		agentConf,
   348  		agentConf,
   349  	)
   350  	// little hack to set the data that Init expects to already be set
   351  	a.(*machineAgentCmd).machineId = "42"
   352  
   353  	// set the value that normally gets set by the flag parsing
   354  	a.(*machineAgentCmd).logToStdErr = true
   355  
   356  	err = a.Init(nil)
   357  	c.Assert(err, gc.IsNil)
   358  
   359  	_, ok := ctx.Stderr.(*lumberjack.Logger)
   360  	c.Assert(ok, jc.IsFalse)
   361  }
   362  
   363  func (s *MachineSuite) TestRunStop(c *gc.C) {
   364  	m, ac, _ := s.primeAgent(c, version.Current, state.JobHostUnits)
   365  	a := s.newAgent(c, m)
   366  	done := make(chan error)
   367  	go func() {
   368  		done <- a.Run(nil)
   369  	}()
   370  	err := a.Stop()
   371  	c.Assert(err, jc.ErrorIsNil)
   372  	c.Assert(<-done, jc.ErrorIsNil)
   373  	c.Assert(charmrepo.CacheDir, gc.Equals, filepath.Join(ac.DataDir(), "charmcache"))
   374  }
   375  
   376  func (s *MachineSuite) TestWithDeadMachine(c *gc.C) {
   377  	m, _, _ := s.primeAgent(c, version.Current, state.JobHostUnits)
   378  	err := m.EnsureDead()
   379  	c.Assert(err, jc.ErrorIsNil)
   380  	a := s.newAgent(c, m)
   381  	err = runWithTimeout(a)
   382  	c.Assert(err, jc.ErrorIsNil)
   383  }
   384  
   385  func (s *MachineSuite) TestWithRemovedMachine(c *gc.C) {
   386  	m, _, _ := s.primeAgent(c, version.Current, state.JobHostUnits)
   387  	err := m.EnsureDead()
   388  	c.Assert(err, jc.ErrorIsNil)
   389  	err = m.Remove()
   390  	c.Assert(err, jc.ErrorIsNil)
   391  	a := s.newAgent(c, m)
   392  	err = runWithTimeout(a)
   393  	c.Assert(err, jc.ErrorIsNil)
   394  }
   395  
   396  func (s *MachineSuite) TestDyingMachine(c *gc.C) {
   397  	m, _, _ := s.primeAgent(c, version.Current, state.JobHostUnits)
   398  	a := s.newAgent(c, m)
   399  	done := make(chan error)
   400  	go func() {
   401  		done <- a.Run(nil)
   402  	}()
   403  	defer func() {
   404  		c.Check(a.Stop(), jc.ErrorIsNil)
   405  	}()
   406  	// Wait for configuration to be finished
   407  	<-a.WorkersStarted()
   408  	err := m.Destroy()
   409  	c.Assert(err, jc.ErrorIsNil)
   410  	select {
   411  	case err := <-done:
   412  		c.Assert(err, jc.ErrorIsNil)
   413  	case <-time.After(watcher.Period * 5 / 4):
   414  		// TODO(rog) Fix this so it doesn't wait for so long.
   415  		// https://bugs.launchpad.net/juju-core/+bug/1163983
   416  		c.Fatalf("timed out waiting for agent to terminate")
   417  	}
   418  	err = m.Refresh()
   419  	c.Assert(err, jc.ErrorIsNil)
   420  	c.Assert(m.Life(), gc.Equals, state.Dead)
   421  }
   422  
   423  func (s *MachineSuite) TestHostUnits(c *gc.C) {
   424  	m, _, _ := s.primeAgent(c, version.Current, state.JobHostUnits)
   425  	a := s.newAgent(c, m)
   426  	ctx, reset := patchDeployContext(c, s.BackingState)
   427  	defer reset()
   428  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
   429  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
   430  
   431  	// check that unassigned units don't trigger any deployments.
   432  	svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   433  	u0, err := svc.AddUnit()
   434  	c.Assert(err, jc.ErrorIsNil)
   435  	u1, err := svc.AddUnit()
   436  	c.Assert(err, jc.ErrorIsNil)
   437  
   438  	ctx.waitDeployed(c)
   439  
   440  	// assign u0, check it's deployed.
   441  	err = u0.AssignToMachine(m)
   442  	c.Assert(err, jc.ErrorIsNil)
   443  	ctx.waitDeployed(c, u0.Name())
   444  
   445  	// "start the agent" for u0 to prevent short-circuited remove-on-destroy;
   446  	// check that it's kept deployed despite being Dying.
   447  	err = u0.SetAgentStatus(state.StatusIdle, "", nil)
   448  	c.Assert(err, jc.ErrorIsNil)
   449  	err = u0.Destroy()
   450  	c.Assert(err, jc.ErrorIsNil)
   451  	ctx.waitDeployed(c, u0.Name())
   452  
   453  	// add u1 to the machine, check it's deployed.
   454  	err = u1.AssignToMachine(m)
   455  	c.Assert(err, jc.ErrorIsNil)
   456  	ctx.waitDeployed(c, u0.Name(), u1.Name())
   457  
   458  	// make u0 dead; check the deployer recalls the unit and removes it from
   459  	// state.
   460  	err = u0.EnsureDead()
   461  	c.Assert(err, jc.ErrorIsNil)
   462  	ctx.waitDeployed(c, u1.Name())
   463  
   464  	// The deployer actually removes the unit just after
   465  	// removing its deployment, so we need to poll here
   466  	// until it actually happens.
   467  	for attempt := coretesting.LongAttempt.Start(); attempt.Next(); {
   468  		err := u0.Refresh()
   469  		if err == nil && attempt.HasNext() {
   470  			continue
   471  		}
   472  		c.Assert(err, jc.Satisfies, errors.IsNotFound)
   473  	}
   474  
   475  	// short-circuit-remove u1 after it's been deployed; check it's recalled
   476  	// and removed from state.
   477  	err = u1.Destroy()
   478  	c.Assert(err, jc.ErrorIsNil)
   479  	err = u1.Refresh()
   480  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   481  	ctx.waitDeployed(c)
   482  }
   483  
   484  func patchDeployContext(c *gc.C, st *state.State) (*fakeContext, func()) {
   485  	ctx := &fakeContext{
   486  		inited:   make(chan struct{}),
   487  		deployed: make(set.Strings),
   488  	}
   489  	orig := newDeployContext
   490  	newDeployContext = func(dst *apideployer.State, agentConfig agent.Config) deployer.Context {
   491  		ctx.st = st
   492  		ctx.agentConfig = agentConfig
   493  		close(ctx.inited)
   494  		return ctx
   495  	}
   496  	return ctx, func() { newDeployContext = orig }
   497  }
   498  
   499  func (s *commonMachineSuite) setFakeMachineAddresses(c *gc.C, machine *state.Machine) {
   500  	addrs := network.NewAddresses("0.1.2.3")
   501  	err := machine.SetProviderAddresses(addrs...)
   502  	c.Assert(err, jc.ErrorIsNil)
   503  	// Set the addresses in the environ instance as well so that if the instance poller
   504  	// runs it won't overwrite them.
   505  	instId, err := machine.InstanceId()
   506  	c.Assert(err, jc.ErrorIsNil)
   507  	insts, err := s.Environ.Instances([]instance.Id{instId})
   508  	c.Assert(err, jc.ErrorIsNil)
   509  	dummy.SetInstanceAddresses(insts[0], addrs)
   510  }
   511  
   512  func (s *MachineSuite) TestManageEnviron(c *gc.C) {
   513  	usefulVersion := version.Current
   514  	usefulVersion.Series = "quantal" // to match the charm created below
   515  	envtesting.AssertUploadFakeToolsVersions(
   516  		c, s.DefaultToolsStorage, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), usefulVersion)
   517  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
   518  	op := make(chan dummy.Operation, 200)
   519  	dummy.Listen(op)
   520  
   521  	a := s.newAgent(c, m)
   522  	// Make sure the agent is stopped even if the test fails.
   523  	defer a.Stop()
   524  	done := make(chan error)
   525  	go func() {
   526  		done <- a.Run(nil)
   527  	}()
   528  
   529  	// See state server runners start
   530  	r0 := s.singularRecord.nextRunner(c)
   531  	r0.waitForWorker(c, "txnpruner")
   532  
   533  	r1 := s.singularRecord.nextRunner(c)
   534  	r1.waitForWorkers(c, perEnvSingularWorkers)
   535  
   536  	// Check that the provisioner and firewaller are alive by doing
   537  	// a rudimentary check that it responds to state changes.
   538  
   539  	// Add one unit to a service; it should get allocated a machine
   540  	// and then its ports should be opened.
   541  	charm := s.AddTestingCharm(c, "dummy")
   542  	svc := s.AddTestingService(c, "test-service", charm)
   543  	err := svc.SetExposed()
   544  	c.Assert(err, jc.ErrorIsNil)
   545  	units, err := juju.AddUnits(s.State, svc, 1, "")
   546  	c.Assert(err, jc.ErrorIsNil)
   547  	c.Check(opRecvTimeout(c, s.State, op, dummy.OpStartInstance{}), gc.NotNil)
   548  
   549  	// Wait for the instance id to show up in the state.
   550  	s.waitProvisioned(c, units[0])
   551  	err = units[0].OpenPort("tcp", 999)
   552  	c.Assert(err, jc.ErrorIsNil)
   553  
   554  	c.Check(opRecvTimeout(c, s.State, op, dummy.OpOpenPorts{}), gc.NotNil)
   555  
   556  	// Check that the metrics workers have started by adding metrics
   557  	select {
   558  	case <-time.After(coretesting.LongWait):
   559  		c.Fatalf("timed out waiting for metric cleanup API to be called")
   560  	case <-s.metricAPI.CleanupCalled():
   561  	}
   562  	select {
   563  	case <-time.After(coretesting.LongWait):
   564  		c.Fatalf("timed out waiting for metric sender API to be called")
   565  	case <-s.metricAPI.SendCalled():
   566  	}
   567  
   568  	err = a.Stop()
   569  	c.Assert(err, jc.ErrorIsNil)
   570  
   571  	select {
   572  	case err := <-done:
   573  		c.Assert(err, jc.ErrorIsNil)
   574  	case <-time.After(5 * time.Second):
   575  		c.Fatalf("timed out waiting for agent to terminate")
   576  	}
   577  }
   578  
   579  func (s *MachineSuite) TestManageEnvironRunsResumer(c *gc.C) {
   580  	started := make(chan struct{})
   581  	s.AgentSuite.PatchValue(&newResumer, func(st resumer.TransactionResumer) *resumer.Resumer {
   582  		close(started)
   583  		return resumer.NewResumer(st)
   584  	})
   585  
   586  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
   587  	a := s.newAgent(c, m)
   588  	defer a.Stop()
   589  	go func() {
   590  		c.Check(a.Run(nil), jc.ErrorIsNil)
   591  	}()
   592  
   593  	// Wait for the worker that starts before the resumer to start.
   594  	_ = s.singularRecord.nextRunner(c)
   595  	r := s.singularRecord.nextRunner(c)
   596  	r.waitForWorker(c, "charm-revision-updater")
   597  
   598  	// Now make sure the resumer starts.
   599  	select {
   600  	case <-started:
   601  	case <-time.After(coretesting.LongWait):
   602  		c.Fatalf("resumer worker not started as expected")
   603  	}
   604  }
   605  
   606  func (s *MachineSuite) TestManageEnvironStartsInstancePoller(c *gc.C) {
   607  	started := make(chan struct{})
   608  	s.AgentSuite.PatchValue(&newInstancePoller, func(st *apiinstancepoller.API) worker.Worker {
   609  		close(started)
   610  		return instancepoller.NewWorker(st)
   611  	})
   612  
   613  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
   614  	a := s.newAgent(c, m)
   615  	defer a.Stop()
   616  	go func() {
   617  		c.Check(a.Run(nil), jc.ErrorIsNil)
   618  	}()
   619  
   620  	// Wait for the worker that starts before the instancepoller to
   621  	// start.
   622  	_ = s.singularRecord.nextRunner(c)
   623  	r := s.singularRecord.nextRunner(c)
   624  	r.waitForWorker(c, "charm-revision-updater")
   625  
   626  	// Now make sure the resumer starts.
   627  	select {
   628  	case <-started:
   629  	case <-time.After(coretesting.LongWait):
   630  		c.Fatalf("instancepoller worker not started as expected")
   631  	}
   632  }
   633  
   634  const startWorkerWait = 250 * time.Millisecond
   635  
   636  func (s *MachineSuite) TestManageEnvironDoesNotRunFirewallerWhenModeIsNone(c *gc.C) {
   637  	s.PatchValue(&getFirewallMode, func(api.Connection) (string, error) {
   638  		return config.FwNone, nil
   639  	})
   640  	started := make(chan struct{})
   641  	s.AgentSuite.PatchValue(&newFirewaller, func(st *apifirewaller.State) (worker.Worker, error) {
   642  		close(started)
   643  		return newDummyWorker(), nil
   644  	})
   645  
   646  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
   647  	a := s.newAgent(c, m)
   648  	defer a.Stop()
   649  	go func() {
   650  		c.Check(a.Run(nil), jc.ErrorIsNil)
   651  	}()
   652  
   653  	// Wait for the worker that starts before the firewaller to start.
   654  	_ = s.singularRecord.nextRunner(c)
   655  	r := s.singularRecord.nextRunner(c)
   656  	r.waitForWorker(c, "charm-revision-updater")
   657  
   658  	// Now make sure the firewaller doesn't start.
   659  	select {
   660  	case <-started:
   661  		c.Fatalf("firewaller worker unexpectedly started")
   662  	case <-time.After(startWorkerWait):
   663  	}
   664  }
   665  
   666  func (s *MachineSuite) TestManageEnvironRunsInstancePoller(c *gc.C) {
   667  	s.AgentSuite.PatchValue(&instancepoller.ShortPoll, 500*time.Millisecond)
   668  	usefulVersion := version.Current
   669  	usefulVersion.Series = "quantal" // to match the charm created below
   670  	envtesting.AssertUploadFakeToolsVersions(
   671  		c, s.DefaultToolsStorage,
   672  		s.Environ.Config().AgentStream(),
   673  		s.Environ.Config().AgentStream(),
   674  		usefulVersion,
   675  	)
   676  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
   677  	a := s.newAgent(c, m)
   678  	defer a.Stop()
   679  	go func() {
   680  		c.Check(a.Run(nil), jc.ErrorIsNil)
   681  	}()
   682  
   683  	// Add one unit to a service;
   684  	charm := s.AddTestingCharm(c, "dummy")
   685  	svc := s.AddTestingService(c, "test-service", charm)
   686  	units, err := juju.AddUnits(s.State, svc, 1, "")
   687  	c.Assert(err, jc.ErrorIsNil)
   688  
   689  	m, instId := s.waitProvisioned(c, units[0])
   690  	insts, err := s.Environ.Instances([]instance.Id{instId})
   691  	c.Assert(err, jc.ErrorIsNil)
   692  	addrs := network.NewAddresses("1.2.3.4")
   693  	dummy.SetInstanceAddresses(insts[0], addrs)
   694  	dummy.SetInstanceStatus(insts[0], "running")
   695  
   696  	for a := coretesting.LongAttempt.Start(); a.Next(); {
   697  		if !a.HasNext() {
   698  			c.Logf("final machine addresses: %#v", m.Addresses())
   699  			c.Fatalf("timed out waiting for machine to get address")
   700  		}
   701  		err := m.Refresh()
   702  		c.Assert(err, jc.ErrorIsNil)
   703  		instStatus, err := m.InstanceStatus()
   704  		c.Assert(err, jc.ErrorIsNil)
   705  		if reflect.DeepEqual(m.Addresses(), addrs) && instStatus == "running" {
   706  			break
   707  		}
   708  	}
   709  }
   710  
   711  func (s *MachineSuite) TestManageEnvironRunsPeergrouper(c *gc.C) {
   712  	started := make(chan struct{}, 1)
   713  	s.AgentSuite.PatchValue(&peergrouperNew, func(st *state.State) (worker.Worker, error) {
   714  		c.Check(st, gc.NotNil)
   715  		select {
   716  		case started <- struct{}{}:
   717  		default:
   718  		}
   719  		return newDummyWorker(), nil
   720  	})
   721  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
   722  	a := s.newAgent(c, m)
   723  	defer a.Stop()
   724  	go func() {
   725  		c.Check(a.Run(nil), jc.ErrorIsNil)
   726  	}()
   727  	select {
   728  	case <-started:
   729  	case <-time.After(coretesting.LongWait):
   730  		c.Fatalf("timed out waiting for peergrouper worker to be started")
   731  	}
   732  }
   733  
   734  func (s *MachineSuite) testAddresserNewWorkerResult(c *gc.C, expectFinished bool) {
   735  	// TODO(dimitern): Fix this in a follow-up.
   736  	c.Skip("Test temporarily disabled as flaky - see bug lp:1488576")
   737  
   738  	started := make(chan struct{})
   739  	s.PatchValue(&newAddresser, func(api *apiaddresser.API) (worker.Worker, error) {
   740  		close(started)
   741  		w, err := addresser.NewWorker(api)
   742  		c.Check(err, jc.ErrorIsNil)
   743  		if expectFinished {
   744  			// When the address-allocation feature flag is disabled.
   745  			c.Check(w, gc.FitsTypeOf, worker.FinishedWorker{})
   746  		} else {
   747  			// When the address-allocation feature flag is enabled.
   748  			c.Check(w, gc.Not(gc.FitsTypeOf), worker.FinishedWorker{})
   749  		}
   750  		return w, err
   751  	})
   752  
   753  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
   754  	a := s.newAgent(c, m)
   755  	defer a.Stop()
   756  	go func() {
   757  		c.Check(a.Run(nil), jc.ErrorIsNil)
   758  	}()
   759  
   760  	// Wait for the worker that starts before the addresser to start.
   761  	_ = s.singularRecord.nextRunner(c)
   762  	r := s.singularRecord.nextRunner(c)
   763  	r.waitForWorker(c, "cleaner")
   764  
   765  	select {
   766  	case <-started:
   767  	case <-time.After(coretesting.LongWait):
   768  		c.Fatalf("timed out waiting for addresser to start")
   769  	}
   770  }
   771  
   772  func (s *MachineSuite) TestAddresserWorkerDoesNotStopWhenAddressDeallocationSupported(c *gc.C) {
   773  	s.SetFeatureFlags(feature.AddressAllocation)
   774  	s.testAddresserNewWorkerResult(c, false)
   775  }
   776  
   777  func (s *MachineSuite) TestAddresserWorkerStopsWhenAddressDeallocationNotSupported(c *gc.C) {
   778  	s.SetFeatureFlags()
   779  	s.testAddresserNewWorkerResult(c, true)
   780  }
   781  
   782  func (s *MachineSuite) TestManageEnvironRunsDbLogPrunerIfFeatureFlagEnabled(c *gc.C) {
   783  	s.SetFeatureFlags("db-log")
   784  
   785  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
   786  	a := s.newAgent(c, m)
   787  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
   788  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
   789  
   790  	runner := s.singularRecord.nextRunner(c)
   791  	runner.waitForWorker(c, "dblogpruner")
   792  }
   793  
   794  func (s *MachineSuite) TestManageEnvironDoesntRunDbLogPrunerByDefault(c *gc.C) {
   795  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
   796  	a := s.newAgent(c, m)
   797  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
   798  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
   799  
   800  	// Wait for the txnpruner to be started. This is started just after
   801  	// dblogpruner would be started.
   802  	runner := s.singularRecord.nextRunner(c)
   803  	started := set.NewStrings(runner.waitForWorker(c, "txnpruner")...)
   804  	c.Assert(started.Contains("dblogpruner"), jc.IsFalse)
   805  }
   806  
   807  func (s *MachineSuite) TestManageEnvironRunsStatusHistoryPruner(c *gc.C) {
   808  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
   809  	a := s.newAgent(c, m)
   810  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
   811  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
   812  
   813  	runner := s.singularRecord.nextRunner(c)
   814  	runner.waitForWorker(c, "statushistorypruner")
   815  }
   816  
   817  func (s *MachineSuite) TestManageEnvironCallsUseMultipleCPUs(c *gc.C) {
   818  	// If it has been enabled, the JobManageEnviron agent should call utils.UseMultipleCPUs
   819  	usefulVersion := version.Current
   820  	usefulVersion.Series = "quantal"
   821  	envtesting.AssertUploadFakeToolsVersions(
   822  		c, s.DefaultToolsStorage, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), usefulVersion)
   823  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
   824  	calledChan := make(chan struct{}, 1)
   825  	s.AgentSuite.PatchValue(&useMultipleCPUs, func() { calledChan <- struct{}{} })
   826  	// Now, start the agent, and observe that a JobManageEnviron agent
   827  	// calls UseMultipleCPUs
   828  	a := s.newAgent(c, m)
   829  	defer a.Stop()
   830  	go func() {
   831  		c.Check(a.Run(nil), jc.ErrorIsNil)
   832  	}()
   833  	// Wait for configuration to be finished
   834  	<-a.WorkersStarted()
   835  	select {
   836  	case <-calledChan:
   837  	case <-time.After(coretesting.LongWait):
   838  		c.Errorf("we failed to call UseMultipleCPUs()")
   839  	}
   840  	c.Check(a.Stop(), jc.ErrorIsNil)
   841  	// However, an agent that just JobHostUnits doesn't call UseMultipleCPUs
   842  	m2, _, _ := s.primeAgent(c, version.Current, state.JobHostUnits)
   843  	a2 := s.newAgent(c, m2)
   844  	defer a2.Stop()
   845  	go func() {
   846  		c.Check(a2.Run(nil), jc.ErrorIsNil)
   847  	}()
   848  	// Wait until all the workers have been started, and then kill everything
   849  	<-a2.workersStarted
   850  	c.Check(a2.Stop(), jc.ErrorIsNil)
   851  	select {
   852  	case <-calledChan:
   853  		c.Errorf("we should not have called UseMultipleCPUs()")
   854  	case <-time.After(coretesting.ShortWait):
   855  	}
   856  }
   857  
   858  func (s *MachineSuite) waitProvisioned(c *gc.C, unit *state.Unit) (*state.Machine, instance.Id) {
   859  	c.Logf("waiting for unit %q to be provisioned", unit)
   860  	machineId, err := unit.AssignedMachineId()
   861  	c.Assert(err, jc.ErrorIsNil)
   862  	m, err := s.State.Machine(machineId)
   863  	c.Assert(err, jc.ErrorIsNil)
   864  	w := m.Watch()
   865  	defer w.Stop()
   866  	timeout := time.After(coretesting.LongWait)
   867  	for {
   868  		select {
   869  		case <-timeout:
   870  			c.Fatalf("timed out waiting for provisioning")
   871  		case _, ok := <-w.Changes():
   872  			c.Assert(ok, jc.IsTrue)
   873  			err := m.Refresh()
   874  			c.Assert(err, jc.ErrorIsNil)
   875  			if instId, err := m.InstanceId(); err == nil {
   876  				c.Logf("unit provisioned with instance %s", instId)
   877  				return m, instId
   878  			} else {
   879  				c.Check(err, jc.Satisfies, errors.IsNotProvisioned)
   880  			}
   881  		}
   882  	}
   883  }
   884  
   885  func (s *MachineSuite) testUpgradeRequest(c *gc.C, agent runner, tag string, currentTools *tools.Tools) {
   886  	newVers := version.Current
   887  	newVers.Patch++
   888  	newTools := envtesting.AssertUploadFakeToolsVersions(
   889  		c, s.DefaultToolsStorage, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), newVers)[0]
   890  	err := s.State.SetEnvironAgentVersion(newVers.Number)
   891  	c.Assert(err, jc.ErrorIsNil)
   892  	err = runWithTimeout(agent)
   893  	envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{
   894  		AgentName: tag,
   895  		OldTools:  currentTools.Version,
   896  		NewTools:  newTools.Version,
   897  		DataDir:   s.DataDir(),
   898  	})
   899  }
   900  
   901  func (s *MachineSuite) TestUpgradeRequest(c *gc.C) {
   902  	m, _, currentTools := s.primeAgent(c, version.Current, state.JobManageEnviron, state.JobHostUnits)
   903  	a := s.newAgent(c, m)
   904  	s.testUpgradeRequest(c, a, m.Tag().String(), currentTools)
   905  	c.Assert(a.isAgentUpgradePending(), jc.IsTrue)
   906  }
   907  
   908  func (s *MachineSuite) TestNoUpgradeRequired(c *gc.C) {
   909  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron, state.JobHostUnits)
   910  	a := s.newAgent(c, m)
   911  	done := make(chan error)
   912  	go func() { done <- a.Run(nil) }()
   913  	select {
   914  	case <-a.initialAgentUpgradeCheckComplete:
   915  	case <-time.After(coretesting.LongWait):
   916  		c.Fatalf("timeout waiting for upgrade check")
   917  	}
   918  	defer a.Stop() // in case of failure
   919  	s.waitStopped(c, state.JobManageEnviron, a, done)
   920  	c.Assert(a.isAgentUpgradePending(), jc.IsFalse)
   921  }
   922  
   923  var fastDialOpts = api.DialOpts{
   924  	Timeout:    coretesting.LongWait,
   925  	RetryDelay: coretesting.ShortWait,
   926  }
   927  
   928  func (s *MachineSuite) waitStopped(c *gc.C, job state.MachineJob, a *MachineAgent, done chan error) {
   929  	err := a.Stop()
   930  	if job == state.JobManageEnviron {
   931  		// When shutting down, the API server can be shut down before
   932  		// the other workers that connect to it, so they get an error so
   933  		// they then die, causing Stop to return an error.  It's not
   934  		// easy to control the actual error that's received in this
   935  		// circumstance so we just log it rather than asserting that it
   936  		// is not nil.
   937  		if err != nil {
   938  			c.Logf("error shutting down state manager: %v", err)
   939  		}
   940  	} else {
   941  		c.Assert(err, jc.ErrorIsNil)
   942  	}
   943  
   944  	select {
   945  	case err := <-done:
   946  		c.Assert(err, jc.ErrorIsNil)
   947  	case <-time.After(5 * time.Second):
   948  		c.Fatalf("timed out waiting for agent to terminate")
   949  	}
   950  }
   951  
   952  func (s *MachineSuite) assertJobWithAPI(
   953  	c *gc.C,
   954  	job state.MachineJob,
   955  	test func(agent.Config, api.Connection),
   956  ) {
   957  	s.assertAgentOpensState(c, &reportOpenedAPI, job, func(cfg agent.Config, st interface{}) {
   958  		test(cfg, st.(api.Connection))
   959  	})
   960  }
   961  
   962  func (s *MachineSuite) assertJobWithState(
   963  	c *gc.C,
   964  	job state.MachineJob,
   965  	test func(agent.Config, *state.State),
   966  ) {
   967  	paramsJob := job.ToParams()
   968  	if !paramsJob.NeedsState() {
   969  		c.Fatalf("%v does not use state", paramsJob)
   970  	}
   971  	s.assertAgentOpensState(c, &reportOpenedState, job, func(cfg agent.Config, st interface{}) {
   972  		test(cfg, st.(*state.State))
   973  	})
   974  }
   975  
   976  // assertAgentOpensState asserts that a machine agent started with the
   977  // given job will call the function pointed to by reportOpened. The
   978  // agent's configuration and the value passed to reportOpened are then
   979  // passed to the test function for further checking.
   980  func (s *MachineSuite) assertAgentOpensState(
   981  	c *gc.C,
   982  	reportOpened *func(io.Closer),
   983  	job state.MachineJob,
   984  	test func(agent.Config, interface{}),
   985  ) {
   986  	stm, conf, _ := s.primeAgent(c, version.Current, job)
   987  	a := s.newAgent(c, stm)
   988  	defer a.Stop()
   989  	logger.Debugf("new agent %#v", a)
   990  
   991  	// All state jobs currently also run an APIWorker, so no
   992  	// need to check for that here, like in assertJobWithState.
   993  
   994  	agentAPIs := make(chan io.Closer, 1)
   995  	s.AgentSuite.PatchValue(reportOpened, func(st io.Closer) {
   996  		select {
   997  		case agentAPIs <- st:
   998  		default:
   999  		}
  1000  	})
  1001  
  1002  	done := make(chan error)
  1003  	go func() {
  1004  		done <- a.Run(nil)
  1005  	}()
  1006  
  1007  	select {
  1008  	case agentAPI := <-agentAPIs:
  1009  		c.Assert(agentAPI, gc.NotNil)
  1010  		test(conf, agentAPI)
  1011  	case <-time.After(coretesting.LongWait):
  1012  		c.Fatalf("API not opened")
  1013  	}
  1014  
  1015  	s.waitStopped(c, job, a, done)
  1016  }
  1017  
  1018  func (s *MachineSuite) TestManageEnvironServesAPI(c *gc.C) {
  1019  	s.assertJobWithState(c, state.JobManageEnviron, func(conf agent.Config, agentState *state.State) {
  1020  		st, err := api.Open(conf.APIInfo(), fastDialOpts)
  1021  		c.Assert(err, jc.ErrorIsNil)
  1022  		defer st.Close()
  1023  		m, err := st.Machiner().Machine(conf.Tag().(names.MachineTag))
  1024  		c.Assert(err, jc.ErrorIsNil)
  1025  		c.Assert(m.Life(), gc.Equals, params.Alive)
  1026  	})
  1027  }
  1028  
  1029  func (s *MachineSuite) assertAgentSetsToolsVersion(c *gc.C, job state.MachineJob) {
  1030  	vers := version.Current
  1031  	vers.Minor = version.Current.Minor + 1
  1032  	m, _, _ := s.primeAgent(c, vers, job)
  1033  	a := s.newAgent(c, m)
  1034  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1035  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1036  
  1037  	timeout := time.After(coretesting.LongWait)
  1038  	for done := false; !done; {
  1039  		select {
  1040  		case <-timeout:
  1041  			c.Fatalf("timeout while waiting for agent version to be set")
  1042  		case <-time.After(coretesting.ShortWait):
  1043  			c.Log("Refreshing")
  1044  			err := m.Refresh()
  1045  			c.Assert(err, jc.ErrorIsNil)
  1046  			c.Log("Fetching agent tools")
  1047  			agentTools, err := m.AgentTools()
  1048  			c.Assert(err, jc.ErrorIsNil)
  1049  			c.Logf("(%v vs. %v)", agentTools.Version, version.Current)
  1050  			if agentTools.Version.Minor != version.Current.Minor {
  1051  				continue
  1052  			}
  1053  			c.Assert(agentTools.Version, gc.DeepEquals, version.Current)
  1054  			done = true
  1055  		}
  1056  	}
  1057  }
  1058  
  1059  func (s *MachineSuite) TestAgentSetsToolsVersionManageEnviron(c *gc.C) {
  1060  	s.assertAgentSetsToolsVersion(c, state.JobManageEnviron)
  1061  }
  1062  
  1063  func (s *MachineSuite) TestAgentSetsToolsVersionHostUnits(c *gc.C) {
  1064  	s.assertAgentSetsToolsVersion(c, state.JobHostUnits)
  1065  }
  1066  
  1067  func (s *MachineSuite) TestManageEnvironRunsCleaner(c *gc.C) {
  1068  	s.assertJobWithState(c, state.JobManageEnviron, func(conf agent.Config, agentState *state.State) {
  1069  		// Create a service and unit, and destroy the service.
  1070  		service := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
  1071  		unit, err := service.AddUnit()
  1072  		c.Assert(err, jc.ErrorIsNil)
  1073  		err = service.Destroy()
  1074  		c.Assert(err, jc.ErrorIsNil)
  1075  
  1076  		// Check the unit was not yet removed.
  1077  		err = unit.Refresh()
  1078  		c.Assert(err, jc.ErrorIsNil)
  1079  		w := unit.Watch()
  1080  		defer w.Stop()
  1081  
  1082  		// Trigger a sync on the state used by the agent, and wait
  1083  		// for the unit to be removed.
  1084  		agentState.StartSync()
  1085  		timeout := time.After(coretesting.LongWait)
  1086  		for done := false; !done; {
  1087  			select {
  1088  			case <-timeout:
  1089  				c.Fatalf("unit not cleaned up")
  1090  			case <-time.After(coretesting.ShortWait):
  1091  				s.State.StartSync()
  1092  			case <-w.Changes():
  1093  				err := unit.Refresh()
  1094  				if errors.IsNotFound(err) {
  1095  					done = true
  1096  				} else {
  1097  					c.Assert(err, jc.ErrorIsNil)
  1098  				}
  1099  			}
  1100  		}
  1101  	})
  1102  }
  1103  
  1104  func (s *MachineSuite) TestJobManageEnvironRunsMinUnitsWorker(c *gc.C) {
  1105  	s.assertJobWithState(c, state.JobManageEnviron, func(conf agent.Config, agentState *state.State) {
  1106  		// Ensure that the MinUnits worker is alive by doing a simple check
  1107  		// that it responds to state changes: add a service, set its minimum
  1108  		// number of units to one, wait for the worker to add the missing unit.
  1109  		service := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
  1110  		err := service.SetMinUnits(1)
  1111  		c.Assert(err, jc.ErrorIsNil)
  1112  		w := service.Watch()
  1113  		defer w.Stop()
  1114  
  1115  		// Trigger a sync on the state used by the agent, and wait for the unit
  1116  		// to be created.
  1117  		agentState.StartSync()
  1118  		timeout := time.After(coretesting.LongWait)
  1119  		for {
  1120  			select {
  1121  			case <-timeout:
  1122  				c.Fatalf("unit not created")
  1123  			case <-time.After(coretesting.ShortWait):
  1124  				s.State.StartSync()
  1125  			case <-w.Changes():
  1126  				units, err := service.AllUnits()
  1127  				c.Assert(err, jc.ErrorIsNil)
  1128  				if len(units) == 1 {
  1129  					return
  1130  				}
  1131  			}
  1132  		}
  1133  	})
  1134  }
  1135  
  1136  func (s *MachineSuite) TestMachineAgentRunsAuthorisedKeysWorker(c *gc.C) {
  1137  	//TODO(bogdanteleaga): Fix once we get authentication worker up on windows
  1138  	if runtime.GOOS == "windows" {
  1139  		c.Skip("bug 1403084: authentication worker not yet implemented on windows")
  1140  	}
  1141  	// Start the machine agent.
  1142  	m, _, _ := s.primeAgent(c, version.Current, state.JobHostUnits)
  1143  	a := s.newAgent(c, m)
  1144  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1145  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1146  
  1147  	// Update the keys in the environment.
  1148  	sshKey := sshtesting.ValidKeyOne.Key + " user@host"
  1149  	err := s.BackingState.UpdateEnvironConfig(map[string]interface{}{"authorized-keys": sshKey}, nil, nil)
  1150  	c.Assert(err, jc.ErrorIsNil)
  1151  
  1152  	// Wait for ssh keys file to be updated.
  1153  	s.State.StartSync()
  1154  	timeout := time.After(coretesting.LongWait)
  1155  	sshKeyWithCommentPrefix := sshtesting.ValidKeyOne.Key + " Juju:user@host"
  1156  	for {
  1157  		select {
  1158  		case <-timeout:
  1159  			c.Fatalf("timeout while waiting for authorised ssh keys to change")
  1160  		case <-time.After(coretesting.ShortWait):
  1161  			keys, err := ssh.ListKeys(authenticationworker.SSHUser, ssh.FullKeys)
  1162  			c.Assert(err, jc.ErrorIsNil)
  1163  			keysStr := strings.Join(keys, "\n")
  1164  			if sshKeyWithCommentPrefix != keysStr {
  1165  				continue
  1166  			}
  1167  			return
  1168  		}
  1169  	}
  1170  }
  1171  
  1172  // opRecvTimeout waits for any of the given kinds of operation to
  1173  // be received from ops, and times out if not.
  1174  func opRecvTimeout(c *gc.C, st *state.State, opc <-chan dummy.Operation, kinds ...dummy.Operation) dummy.Operation {
  1175  	st.StartSync()
  1176  	for {
  1177  		select {
  1178  		case op := <-opc:
  1179  			for _, k := range kinds {
  1180  				if reflect.TypeOf(op) == reflect.TypeOf(k) {
  1181  					return op
  1182  				}
  1183  			}
  1184  			c.Logf("discarding unknown event %#v", op)
  1185  		case <-time.After(15 * time.Second):
  1186  			c.Fatalf("time out wating for operation")
  1187  		}
  1188  	}
  1189  }
  1190  
  1191  func (s *MachineSuite) TestOpenStateFailsForJobHostUnits(c *gc.C) {
  1192  	s.assertJobWithAPI(c, state.JobHostUnits, func(conf agent.Config, st api.Connection) {
  1193  		s.AssertCannotOpenState(c, conf.Tag(), conf.DataDir())
  1194  	})
  1195  }
  1196  
  1197  func (s *MachineSuite) TestOpenStateFailsForJobManageNetworking(c *gc.C) {
  1198  	s.assertJobWithAPI(c, state.JobManageNetworking, func(conf agent.Config, st api.Connection) {
  1199  		s.AssertCannotOpenState(c, conf.Tag(), conf.DataDir())
  1200  	})
  1201  }
  1202  
  1203  func (s *MachineSuite) TestOpenStateWorksForJobManageEnviron(c *gc.C) {
  1204  	s.assertJobWithAPI(c, state.JobManageEnviron, func(conf agent.Config, st api.Connection) {
  1205  		s.AssertCanOpenState(c, conf.Tag(), conf.DataDir())
  1206  	})
  1207  }
  1208  
  1209  func (s *MachineSuite) TestOpenAPIStateWorksForJobHostUnits(c *gc.C) {
  1210  	machine, conf, _ := s.primeAgent(c, version.Current, state.JobHostUnits)
  1211  	s.runOpenAPISTateTest(c, machine, conf)
  1212  }
  1213  
  1214  func (s *MachineSuite) TestOpenAPIStateWorksForJobManageNetworking(c *gc.C) {
  1215  	machine, conf, _ := s.primeAgent(c, version.Current, state.JobManageNetworking)
  1216  	s.runOpenAPISTateTest(c, machine, conf)
  1217  }
  1218  
  1219  func (s *MachineSuite) TestOpenAPIStateWorksForJobManageEnviron(c *gc.C) {
  1220  	machine, conf, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
  1221  	s.runOpenAPISTateTest(c, machine, conf)
  1222  }
  1223  
  1224  func (s *MachineSuite) runOpenAPISTateTest(c *gc.C, machine *state.Machine, conf agent.Config) {
  1225  	configPath := agent.ConfigPath(conf.DataDir(), conf.Tag())
  1226  
  1227  	// Set a failing password...
  1228  	confW, err := agent.ReadConfig(configPath)
  1229  	c.Assert(err, jc.ErrorIsNil)
  1230  	confW.SetPassword("not-set-on-state-server")
  1231  
  1232  	// ...and also make sure the api info points to the testing api
  1233  	// server (and not, as for JobManageEnviron machines, to the port
  1234  	// chosen for the agent's own API server to run on. This is usually
  1235  	// sane, but inconvenient here because we're not running the full
  1236  	// agent and so the configured API server is not actually there).
  1237  	apiInfo := s.APIInfo(c)
  1238  	hostPorts, err := network.ParseHostPorts(apiInfo.Addrs...)
  1239  	c.Assert(err, jc.ErrorIsNil)
  1240  	confW.SetAPIHostPorts([][]network.HostPort{hostPorts})
  1241  	err = confW.Write()
  1242  	c.Assert(err, jc.ErrorIsNil)
  1243  
  1244  	// Check that it successfully connects with the conf's old password.
  1245  	assertOpen := func() {
  1246  		tagString := conf.Tag().String()
  1247  		agent := NewAgentConf(conf.DataDir())
  1248  		err := agent.ReadConfig(tagString)
  1249  		c.Assert(err, jc.ErrorIsNil)
  1250  		st, gotEntity, err := apicaller.OpenAPIState(agent)
  1251  		c.Assert(err, jc.ErrorIsNil)
  1252  		c.Assert(st, gc.NotNil)
  1253  		st.Close()
  1254  		c.Assert(gotEntity.Tag(), gc.Equals, tagString)
  1255  	}
  1256  	assertOpen()
  1257  
  1258  	// Check that the initial password is no longer valid.
  1259  	assertPassword := func(password string, valid bool) {
  1260  		err := machine.Refresh()
  1261  		c.Assert(err, jc.ErrorIsNil)
  1262  		c.Check(machine.PasswordValid(password), gc.Equals, valid)
  1263  	}
  1264  	assertPassword(initialMachinePassword, false)
  1265  
  1266  	// Read the configuration and check that we can connect with it.
  1267  	confR, err := agent.ReadConfig(configPath)
  1268  	c.Assert(err, gc.IsNil)
  1269  	newPassword := confR.APIInfo().Password
  1270  	assertPassword(newPassword, true)
  1271  
  1272  	// Double-check that we can open a fresh connection with the stored
  1273  	// conf ... and that the password hasn't been changed again.
  1274  	assertOpen()
  1275  	assertPassword(newPassword, true)
  1276  }
  1277  
  1278  func (s *MachineSuite) TestMachineAgentSymlinkJujuRun(c *gc.C) {
  1279  	_, err := os.Stat(JujuRun)
  1280  	c.Assert(err, jc.Satisfies, os.IsNotExist)
  1281  	s.assertJobWithAPI(c, state.JobManageEnviron, func(conf agent.Config, st api.Connection) {
  1282  		// juju-run should have been created
  1283  		_, err := os.Stat(JujuRun)
  1284  		c.Assert(err, jc.ErrorIsNil)
  1285  	})
  1286  }
  1287  
  1288  func (s *MachineSuite) TestMachineAgentSymlinkJujuRunExists(c *gc.C) {
  1289  	if runtime.GOOS == "windows" {
  1290  		// Cannot make symlink to nonexistent file on windows or
  1291  		// create a file point a symlink to it then remove it
  1292  		c.Skip("Cannot test this on windows")
  1293  	}
  1294  	err := symlink.New("/nowhere/special", JujuRun)
  1295  	c.Assert(err, jc.ErrorIsNil)
  1296  	_, err = os.Stat(JujuRun)
  1297  	c.Assert(err, jc.Satisfies, os.IsNotExist)
  1298  	s.assertJobWithAPI(c, state.JobManageEnviron, func(conf agent.Config, st api.Connection) {
  1299  		// juju-run should have been recreated
  1300  		_, err := os.Stat(JujuRun)
  1301  		c.Assert(err, jc.ErrorIsNil)
  1302  		link, err := symlink.Read(JujuRun)
  1303  		c.Assert(err, jc.ErrorIsNil)
  1304  		c.Assert(link, gc.Not(gc.Equals), "/nowhere/special")
  1305  	})
  1306  }
  1307  
  1308  func (s *MachineSuite) TestProxyUpdater(c *gc.C) {
  1309  	s.assertProxyUpdater(c, true)
  1310  	s.assertProxyUpdater(c, false)
  1311  }
  1312  
  1313  func (s *MachineSuite) assertProxyUpdater(c *gc.C, expectWriteSystemFiles bool) {
  1314  	// Patch out the func that decides whether we should write system files.
  1315  	var gotConf agent.Config
  1316  	s.AgentSuite.PatchValue(&shouldWriteProxyFiles, func(conf agent.Config) bool {
  1317  		gotConf = conf
  1318  		return expectWriteSystemFiles
  1319  	})
  1320  
  1321  	// Make sure there are some proxy settings to write.
  1322  	expectSettings := proxy.Settings{
  1323  		Http:  "http proxy",
  1324  		Https: "https proxy",
  1325  		Ftp:   "ftp proxy",
  1326  	}
  1327  	updateAttrs := config.ProxyConfigMap(expectSettings)
  1328  	err := s.State.UpdateEnvironConfig(updateAttrs, nil, nil)
  1329  	c.Assert(err, jc.ErrorIsNil)
  1330  
  1331  	// Patch out the actual worker func.
  1332  	started := make(chan struct{})
  1333  	mockNew := func(api *apienvironment.Facade, writeSystemFiles bool) worker.Worker {
  1334  		// Direct check of the behaviour flag.
  1335  		c.Check(writeSystemFiles, gc.Equals, expectWriteSystemFiles)
  1336  		// Indirect check that we get a functional API.
  1337  		conf, err := api.EnvironConfig()
  1338  		if c.Check(err, jc.ErrorIsNil) {
  1339  			actualSettings := conf.ProxySettings()
  1340  			c.Check(actualSettings, jc.DeepEquals, expectSettings)
  1341  		}
  1342  		return worker.NewSimpleWorker(func(_ <-chan struct{}) error {
  1343  			close(started)
  1344  			return nil
  1345  		})
  1346  	}
  1347  	s.AgentSuite.PatchValue(&proxyupdater.New, mockNew)
  1348  
  1349  	s.primeAgent(c, version.Current, state.JobHostUnits)
  1350  	s.assertJobWithAPI(c, state.JobHostUnits, func(conf agent.Config, st api.Connection) {
  1351  		for {
  1352  			select {
  1353  			case <-time.After(coretesting.LongWait):
  1354  				c.Fatalf("timeout while waiting for proxy updater to start")
  1355  			case <-started:
  1356  				c.Assert(gotConf, jc.DeepEquals, conf)
  1357  				return
  1358  			}
  1359  		}
  1360  	})
  1361  }
  1362  
  1363  func (s *MachineSuite) TestMachineAgentUninstall(c *gc.C) {
  1364  	m, ac, _ := s.primeAgent(c, version.Current, state.JobHostUnits)
  1365  	err := m.EnsureDead()
  1366  	c.Assert(err, jc.ErrorIsNil)
  1367  	a := s.newAgent(c, m)
  1368  	err = runWithTimeout(a)
  1369  	c.Assert(err, jc.ErrorIsNil)
  1370  	// juju-run should have been removed on termination
  1371  	_, err = os.Stat(JujuRun)
  1372  	c.Assert(err, jc.Satisfies, os.IsNotExist)
  1373  	// data-dir should have been removed on termination
  1374  	_, err = os.Stat(ac.DataDir())
  1375  	c.Assert(err, jc.Satisfies, os.IsNotExist)
  1376  }
  1377  
  1378  func (s *MachineSuite) TestMachineAgentRsyslogManageEnviron(c *gc.C) {
  1379  	s.testMachineAgentRsyslogConfigWorker(c, state.JobManageEnviron, rsyslog.RsyslogModeAccumulate)
  1380  }
  1381  
  1382  func (s *MachineSuite) TestMachineAgentRsyslogHostUnits(c *gc.C) {
  1383  	s.testMachineAgentRsyslogConfigWorker(c, state.JobHostUnits, rsyslog.RsyslogModeForwarding)
  1384  }
  1385  
  1386  func (s *MachineSuite) testMachineAgentRsyslogConfigWorker(c *gc.C, job state.MachineJob, expectedMode rsyslog.RsyslogMode) {
  1387  	created := make(chan rsyslog.RsyslogMode, 1)
  1388  	s.AgentSuite.PatchValue(&cmdutil.NewRsyslogConfigWorker, func(_ *apirsyslog.State, _ agent.Config, mode rsyslog.RsyslogMode) (worker.Worker, error) {
  1389  		created <- mode
  1390  		return newDummyWorker(), nil
  1391  	})
  1392  	s.assertJobWithAPI(c, job, func(conf agent.Config, st api.Connection) {
  1393  		select {
  1394  		case <-time.After(coretesting.LongWait):
  1395  			c.Fatalf("timeout while waiting for rsyslog worker to be created")
  1396  		case mode := <-created:
  1397  			c.Assert(mode, gc.Equals, expectedMode)
  1398  		}
  1399  	})
  1400  }
  1401  
  1402  func (s *MachineSuite) TestMachineAgentRunsAPIAddressUpdaterWorker(c *gc.C) {
  1403  	// Start the machine agent.
  1404  	m, _, _ := s.primeAgent(c, version.Current, state.JobHostUnits)
  1405  	a := s.newAgent(c, m)
  1406  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1407  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1408  
  1409  	// Update the API addresses.
  1410  	updatedServers := [][]network.HostPort{
  1411  		network.NewHostPorts(1234, "localhost"),
  1412  	}
  1413  	err := s.BackingState.SetAPIHostPorts(updatedServers)
  1414  	c.Assert(err, jc.ErrorIsNil)
  1415  
  1416  	// Wait for config to be updated.
  1417  	s.BackingState.StartSync()
  1418  	for attempt := coretesting.LongAttempt.Start(); attempt.Next(); {
  1419  		addrs, err := a.CurrentConfig().APIAddresses()
  1420  		c.Assert(err, jc.ErrorIsNil)
  1421  		if reflect.DeepEqual(addrs, []string{"localhost:1234"}) {
  1422  			return
  1423  		}
  1424  	}
  1425  	c.Fatalf("timeout while waiting for agent config to change")
  1426  }
  1427  
  1428  func (s *MachineSuite) TestMachineAgentRunsDiskManagerWorker(c *gc.C) {
  1429  	// Patch out the worker func before starting the agent.
  1430  	started := make(chan struct{})
  1431  	newWorker := func(diskmanager.ListBlockDevicesFunc, diskmanager.BlockDeviceSetter) worker.Worker {
  1432  		close(started)
  1433  		return worker.NewNoOpWorker()
  1434  	}
  1435  	s.PatchValue(&newDiskManager, newWorker)
  1436  
  1437  	// Start the machine agent.
  1438  	m, _, _ := s.primeAgent(c, version.Current, state.JobHostUnits)
  1439  	a := s.newAgent(c, m)
  1440  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1441  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1442  
  1443  	// Wait for worker to be started.
  1444  	select {
  1445  	case <-started:
  1446  	case <-time.After(coretesting.LongWait):
  1447  		c.Fatalf("timeout while waiting for diskmanager worker to start")
  1448  	}
  1449  }
  1450  
  1451  func (s *MachineSuite) TestDiskManagerWorkerUpdatesState(c *gc.C) {
  1452  	expected := []storage.BlockDevice{{DeviceName: "whatever"}}
  1453  	s.PatchValue(&diskmanager.DefaultListBlockDevices, func() ([]storage.BlockDevice, error) {
  1454  		return expected, nil
  1455  	})
  1456  
  1457  	// Start the machine agent.
  1458  	m, _, _ := s.primeAgent(c, version.Current, state.JobHostUnits)
  1459  	a := s.newAgent(c, m)
  1460  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1461  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1462  
  1463  	// Wait for state to be updated.
  1464  	s.BackingState.StartSync()
  1465  	for attempt := coretesting.LongAttempt.Start(); attempt.Next(); {
  1466  		devices, err := s.BackingState.BlockDevices(m.MachineTag())
  1467  		c.Assert(err, jc.ErrorIsNil)
  1468  		if len(devices) > 0 {
  1469  			c.Assert(devices, gc.HasLen, 1)
  1470  			c.Assert(devices[0].DeviceName, gc.Equals, expected[0].DeviceName)
  1471  			return
  1472  		}
  1473  	}
  1474  	c.Fatalf("timeout while waiting for block devices to be recorded")
  1475  }
  1476  
  1477  func (s *MachineSuite) TestMachineAgentDoesNotRunMetadataWorkerForHostUnits(c *gc.C) {
  1478  	s.checkMetadataWorkerNotRun(c, state.JobHostUnits, "can host units")
  1479  }
  1480  
  1481  func (s *MachineSuite) TestMachineAgentDoesNotRunMetadataWorkerForManageNetworking(c *gc.C) {
  1482  	s.checkMetadataWorkerNotRun(c, state.JobManageNetworking, "can manage networking")
  1483  }
  1484  
  1485  func (s *MachineSuite) TestMachineAgentDoesNotRunMetadataWorkerForManageStateDeprecated(c *gc.C) {
  1486  	s.checkMetadataWorkerNotRun(c, state.JobManageStateDeprecated, "can manage state (deprecated)")
  1487  }
  1488  
  1489  func (s *MachineSuite) checkMetadataWorkerNotRun(c *gc.C, job state.MachineJob, suffix string) {
  1490  	// Patch out the worker func before starting the agent.
  1491  	started := make(chan struct{})
  1492  	newWorker := func(cl *imagemetadata.Client) worker.Worker {
  1493  		close(started)
  1494  		return worker.NewNoOpWorker()
  1495  	}
  1496  	s.PatchValue(&newMetadataUpdater, newWorker)
  1497  
  1498  	// Start the machine agent.
  1499  	m, _, _ := s.primeAgent(c, version.Current, job)
  1500  	a := s.newAgent(c, m)
  1501  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1502  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1503  
  1504  	// Wait for worker to be started.
  1505  	select {
  1506  	case <-started:
  1507  		c.Fatalf("metadata update worker unexpectedly started for non-state server machine that %v", suffix)
  1508  	case <-time.After(coretesting.ShortWait):
  1509  	}
  1510  }
  1511  
  1512  func (s *MachineSuite) TestMachineAgentRunsMetadataWorker(c *gc.C) {
  1513  	// Patch out the worker func before starting the agent.
  1514  	started := make(chan struct{})
  1515  	newWorker := func(cl *imagemetadata.Client) worker.Worker {
  1516  		close(started)
  1517  		return worker.NewNoOpWorker()
  1518  	}
  1519  	s.PatchValue(&newMetadataUpdater, newWorker)
  1520  
  1521  	// Start the machine agent.
  1522  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
  1523  	a := s.newAgent(c, m)
  1524  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1525  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1526  
  1527  	// Wait for worker to be started.
  1528  	select {
  1529  	case <-started:
  1530  	case <-time.After(coretesting.LongWait):
  1531  		c.Fatalf("timeout while waiting for metadata update worker to start")
  1532  	}
  1533  }
  1534  
  1535  func (s *MachineSuite) TestMachineAgentRunsMachineStorageWorker(c *gc.C) {
  1536  	m, _, _ := s.primeAgent(c, version.Current, state.JobHostUnits)
  1537  
  1538  	started := make(chan struct{})
  1539  	newWorker := func(
  1540  		scope names.Tag,
  1541  		storageDir string,
  1542  		_ storageprovisioner.VolumeAccessor,
  1543  		_ storageprovisioner.FilesystemAccessor,
  1544  		_ storageprovisioner.LifecycleManager,
  1545  		_ storageprovisioner.EnvironAccessor,
  1546  		_ storageprovisioner.MachineAccessor,
  1547  		_ storageprovisioner.StatusSetter,
  1548  		_ clock.Clock,
  1549  	) worker.Worker {
  1550  		c.Check(scope, gc.Equals, m.Tag())
  1551  		// storageDir is not empty for machine scoped storage provisioners
  1552  		c.Assert(storageDir, gc.Not(gc.Equals), "")
  1553  		close(started)
  1554  		return worker.NewNoOpWorker()
  1555  	}
  1556  	s.PatchValue(&newStorageWorker, newWorker)
  1557  
  1558  	// Start the machine agent.
  1559  	a := s.newAgent(c, m)
  1560  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1561  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1562  
  1563  	// Wait for worker to be started.
  1564  	select {
  1565  	case <-started:
  1566  	case <-time.After(coretesting.LongWait):
  1567  		c.Fatalf("timeout while waiting for storage worker to start")
  1568  	}
  1569  }
  1570  
  1571  func (s *MachineSuite) TestMachineAgentRunsEnvironStorageWorker(c *gc.C) {
  1572  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
  1573  
  1574  	var numWorkers, machineWorkers, environWorkers uint32
  1575  	started := make(chan struct{})
  1576  	newWorker := func(
  1577  		scope names.Tag,
  1578  		storageDir string,
  1579  		_ storageprovisioner.VolumeAccessor,
  1580  		_ storageprovisioner.FilesystemAccessor,
  1581  		_ storageprovisioner.LifecycleManager,
  1582  		_ storageprovisioner.EnvironAccessor,
  1583  		_ storageprovisioner.MachineAccessor,
  1584  		_ storageprovisioner.StatusSetter,
  1585  		_ clock.Clock,
  1586  	) worker.Worker {
  1587  		// storageDir is empty for environ storage provisioners
  1588  		if storageDir == "" {
  1589  			c.Check(scope, gc.Equals, s.State.EnvironTag())
  1590  			c.Check(atomic.AddUint32(&environWorkers, 1), gc.Equals, uint32(1))
  1591  			atomic.AddUint32(&numWorkers, 1)
  1592  		}
  1593  		if storageDir != "" {
  1594  			c.Check(scope, gc.Equals, m.Tag())
  1595  			c.Check(atomic.AddUint32(&machineWorkers, 1), gc.Equals, uint32(1))
  1596  			atomic.AddUint32(&numWorkers, 1)
  1597  		}
  1598  		if atomic.LoadUint32(&environWorkers) == 1 && atomic.LoadUint32(&machineWorkers) == 1 {
  1599  			close(started)
  1600  		}
  1601  		return worker.NewNoOpWorker()
  1602  	}
  1603  	s.PatchValue(&newStorageWorker, newWorker)
  1604  
  1605  	// Start the machine agent.
  1606  	a := s.newAgent(c, m)
  1607  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1608  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1609  
  1610  	// Wait for worker to be started.
  1611  	select {
  1612  	case <-started:
  1613  		c.Assert(atomic.LoadUint32(&numWorkers), gc.Equals, uint32(2))
  1614  	case <-time.After(coretesting.LongWait):
  1615  		c.Fatalf("timeout while waiting for storage worker to start")
  1616  	}
  1617  }
  1618  
  1619  func (s *MachineSuite) TestMachineAgentRunsCertificateUpdateWorkerForStateServer(c *gc.C) {
  1620  	started := make(chan struct{})
  1621  	newUpdater := func(certupdater.AddressWatcher, certupdater.StateServingInfoGetter, certupdater.EnvironConfigGetter,
  1622  		certupdater.APIHostPortsGetter, certupdater.StateServingInfoSetter,
  1623  	) worker.Worker {
  1624  		close(started)
  1625  		return worker.NewNoOpWorker()
  1626  	}
  1627  	s.PatchValue(&newCertificateUpdater, newUpdater)
  1628  
  1629  	// Start the machine agent.
  1630  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
  1631  	a := s.newAgent(c, m)
  1632  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1633  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1634  
  1635  	// Wait for worker to be started.
  1636  	select {
  1637  	case <-started:
  1638  	case <-time.After(coretesting.LongWait):
  1639  		c.Fatalf("timeout while waiting for certificate update worker to start")
  1640  	}
  1641  }
  1642  
  1643  func (s *MachineSuite) TestMachineAgentDoesNotRunsCertificateUpdateWorkerForNonStateServer(c *gc.C) {
  1644  	started := make(chan struct{})
  1645  	newUpdater := func(certupdater.AddressWatcher, certupdater.StateServingInfoGetter, certupdater.EnvironConfigGetter,
  1646  		certupdater.APIHostPortsGetter, certupdater.StateServingInfoSetter,
  1647  	) worker.Worker {
  1648  		close(started)
  1649  		return worker.NewNoOpWorker()
  1650  	}
  1651  	s.PatchValue(&newCertificateUpdater, newUpdater)
  1652  
  1653  	// Start the machine agent.
  1654  	m, _, _ := s.primeAgent(c, version.Current, state.JobHostUnits)
  1655  	a := s.newAgent(c, m)
  1656  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1657  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1658  
  1659  	// Ensure the worker is not started.
  1660  	select {
  1661  	case <-started:
  1662  		c.Fatalf("certificate update worker unexpectedly started")
  1663  	case <-time.After(coretesting.ShortWait):
  1664  	}
  1665  }
  1666  
  1667  func (s *MachineSuite) TestCertificateUpdateWorkerUpdatesCertificate(c *gc.C) {
  1668  	// Set up the machine agent.
  1669  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
  1670  	a := s.newAgent(c, m)
  1671  	a.ReadConfig(names.NewMachineTag(m.Id()).String())
  1672  
  1673  	// Set up check that certificate has been updated.
  1674  	updated := make(chan struct{})
  1675  	go func() {
  1676  		for {
  1677  			stateInfo, _ := a.CurrentConfig().StateServingInfo()
  1678  			srvCert, err := cert.ParseCert(stateInfo.Cert)
  1679  			c.Assert(err, jc.ErrorIsNil)
  1680  			sanIPs := make([]string, len(srvCert.IPAddresses))
  1681  			for i, ip := range srvCert.IPAddresses {
  1682  				sanIPs[i] = ip.String()
  1683  			}
  1684  			if len(sanIPs) == 1 && sanIPs[0] == "0.1.2.3" {
  1685  				close(updated)
  1686  				break
  1687  			}
  1688  			time.Sleep(10 * time.Millisecond)
  1689  		}
  1690  	}()
  1691  
  1692  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1693  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1694  	// Wait for certificate to be updated.
  1695  	select {
  1696  	case <-updated:
  1697  	case <-time.After(coretesting.LongWait):
  1698  		c.Fatalf("timeout while waiting for certificate to be updated")
  1699  	}
  1700  }
  1701  
  1702  func (s *MachineSuite) TestCertificateDNSUpdated(c *gc.C) {
  1703  	// Disable the certificate work so it doesn't update the certificate.
  1704  	newUpdater := func(certupdater.AddressWatcher, certupdater.StateServingInfoGetter, certupdater.EnvironConfigGetter,
  1705  		certupdater.APIHostPortsGetter, certupdater.StateServingInfoSetter,
  1706  	) worker.Worker {
  1707  		return worker.NewNoOpWorker()
  1708  	}
  1709  	s.PatchValue(&newCertificateUpdater, newUpdater)
  1710  
  1711  	// Set up the machine agent.
  1712  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
  1713  	a := s.newAgent(c, m)
  1714  
  1715  	// Set up check that certificate has been updated when the agent starts.
  1716  	updated := make(chan struct{})
  1717  	expectedDnsNames := set.NewStrings("local", "juju-apiserver", "juju-mongodb")
  1718  	go func() {
  1719  		for {
  1720  			stateInfo, _ := a.CurrentConfig().StateServingInfo()
  1721  			srvCert, err := cert.ParseCert(stateInfo.Cert)
  1722  			c.Assert(err, jc.ErrorIsNil)
  1723  			certDnsNames := set.NewStrings(srvCert.DNSNames...)
  1724  			if !expectedDnsNames.Difference(certDnsNames).IsEmpty() {
  1725  				continue
  1726  			}
  1727  			pemContent, err := ioutil.ReadFile(filepath.Join(s.DataDir(), "server.pem"))
  1728  			c.Assert(err, jc.ErrorIsNil)
  1729  			if string(pemContent) == stateInfo.Cert+"\n"+stateInfo.PrivateKey {
  1730  				close(updated)
  1731  				break
  1732  			}
  1733  			time.Sleep(10 * time.Millisecond)
  1734  		}
  1735  	}()
  1736  
  1737  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1738  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1739  	// Wait for certificate to be updated.
  1740  	select {
  1741  	case <-updated:
  1742  	case <-time.After(coretesting.LongWait):
  1743  		c.Fatalf("timeout while waiting for certificate to be updated")
  1744  	}
  1745  }
  1746  
  1747  func (s *MachineSuite) TestMachineAgentNetworkerMode(c *gc.C) {
  1748  	tests := []struct {
  1749  		about          string
  1750  		managedNetwork bool
  1751  		jobs           []state.MachineJob
  1752  		intrusiveMode  bool
  1753  	}{{
  1754  		about:          "network management enabled, network management job set",
  1755  		managedNetwork: true,
  1756  		jobs:           []state.MachineJob{state.JobHostUnits, state.JobManageNetworking},
  1757  		intrusiveMode:  true,
  1758  	}, {
  1759  		about:          "network management disabled, network management job set",
  1760  		managedNetwork: false,
  1761  		jobs:           []state.MachineJob{state.JobHostUnits, state.JobManageNetworking},
  1762  		intrusiveMode:  false,
  1763  	}, {
  1764  		about:          "network management enabled, network management job not set",
  1765  		managedNetwork: true,
  1766  		jobs:           []state.MachineJob{state.JobHostUnits},
  1767  		intrusiveMode:  false,
  1768  	}, {
  1769  		about:          "network management disabled, network management job not set",
  1770  		managedNetwork: false,
  1771  		jobs:           []state.MachineJob{state.JobHostUnits},
  1772  		intrusiveMode:  false,
  1773  	}}
  1774  	// Perform tests.
  1775  	for i, test := range tests {
  1776  		c.Logf("test #%d: %s", i, test.about)
  1777  
  1778  		modeCh := make(chan bool, 1)
  1779  		s.AgentSuite.PatchValue(&newNetworker, func(
  1780  			st apinetworker.State,
  1781  			conf agent.Config,
  1782  			intrusiveMode bool,
  1783  			configBaseDir string,
  1784  		) (*networker.Networker, error) {
  1785  			select {
  1786  			case modeCh <- intrusiveMode:
  1787  			default:
  1788  			}
  1789  			return networker.NewNetworker(st, conf, intrusiveMode, configBaseDir)
  1790  		})
  1791  
  1792  		attrs := coretesting.Attrs{"disable-network-management": !test.managedNetwork}
  1793  		err := s.BackingState.UpdateEnvironConfig(attrs, nil, nil)
  1794  		c.Assert(err, jc.ErrorIsNil)
  1795  
  1796  		m, _, _ := s.primeAgent(c, version.Current, test.jobs...)
  1797  		a := s.newAgent(c, m)
  1798  		defer a.Stop()
  1799  		doneCh := make(chan error)
  1800  		go func() {
  1801  			doneCh <- a.Run(nil)
  1802  		}()
  1803  
  1804  		select {
  1805  		case intrusiveMode := <-modeCh:
  1806  			if intrusiveMode != test.intrusiveMode {
  1807  				c.Fatalf("expected networker intrusive mode = %v, got mode = %v", test.intrusiveMode, intrusiveMode)
  1808  			}
  1809  		case <-time.After(coretesting.LongWait):
  1810  			c.Fatalf("timed out waiting for the networker to start")
  1811  		}
  1812  		s.waitStopped(c, state.JobManageNetworking, a, doneCh)
  1813  	}
  1814  }
  1815  
  1816  func (s *MachineSuite) TestMachineAgentIgnoreAddresses(c *gc.C) {
  1817  	for _, expectedIgnoreValue := range []bool{true, false} {
  1818  		ignoreAddressCh := make(chan bool, 1)
  1819  		s.AgentSuite.PatchValue(&newMachiner, func(
  1820  			accessor machiner.MachineAccessor,
  1821  			conf agent.Config,
  1822  			ignoreMachineAddresses bool,
  1823  		) worker.Worker {
  1824  			select {
  1825  			case ignoreAddressCh <- ignoreMachineAddresses:
  1826  			default:
  1827  			}
  1828  			return machiner.NewMachiner(accessor, conf, ignoreMachineAddresses)
  1829  		})
  1830  
  1831  		attrs := coretesting.Attrs{"ignore-machine-addresses": expectedIgnoreValue}
  1832  		err := s.BackingState.UpdateEnvironConfig(attrs, nil, nil)
  1833  		c.Assert(err, jc.ErrorIsNil)
  1834  
  1835  		m, _, _ := s.primeAgent(c, version.Current, state.JobHostUnits)
  1836  		a := s.newAgent(c, m)
  1837  		defer a.Stop()
  1838  		doneCh := make(chan error)
  1839  		go func() {
  1840  			doneCh <- a.Run(nil)
  1841  		}()
  1842  
  1843  		select {
  1844  		case ignoreMachineAddresses := <-ignoreAddressCh:
  1845  			if ignoreMachineAddresses != expectedIgnoreValue {
  1846  				c.Fatalf("expected ignore-machine-addresses = %v, got = %v", expectedIgnoreValue, ignoreMachineAddresses)
  1847  			}
  1848  		case <-time.After(coretesting.LongWait):
  1849  			c.Fatalf("timed out waiting for the machiner to start")
  1850  		}
  1851  		s.waitStopped(c, state.JobHostUnits, a, doneCh)
  1852  	}
  1853  }
  1854  
  1855  func (s *MachineSuite) TestMachineAgentUpgradeMongo(c *gc.C) {
  1856  	m, agentConfig, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
  1857  	agentConfig.SetUpgradedToVersion(version.MustParse("1.18.0"))
  1858  	err := agentConfig.Write()
  1859  	c.Assert(err, jc.ErrorIsNil)
  1860  	err = s.State.MongoSession().DB("admin").RemoveUser(m.Tag().String())
  1861  	c.Assert(err, jc.ErrorIsNil)
  1862  
  1863  	s.fakeEnsureMongo.ServiceInstalled = true
  1864  	s.fakeEnsureMongo.ReplicasetInitiated = false
  1865  
  1866  	s.AgentSuite.PatchValue(&ensureMongoAdminUser, func(p mongo.EnsureAdminUserParams) (bool, error) {
  1867  		err := s.State.MongoSession().DB("admin").AddUser(p.User, p.Password, false)
  1868  		c.Assert(err, jc.ErrorIsNil)
  1869  		return true, nil
  1870  	})
  1871  
  1872  	stateOpened := make(chan interface{}, 1)
  1873  	s.AgentSuite.PatchValue(&reportOpenedState, func(st io.Closer) {
  1874  		select {
  1875  		case stateOpened <- st:
  1876  		default:
  1877  		}
  1878  	})
  1879  
  1880  	// Start the machine agent, and wait for state to be opened.
  1881  	a := s.newAgent(c, m)
  1882  	done := make(chan error)
  1883  	go func() { done <- a.Run(nil) }()
  1884  	defer a.Stop() // in case of failure
  1885  	select {
  1886  	case st := <-stateOpened:
  1887  		c.Assert(st, gc.NotNil)
  1888  	case <-time.After(coretesting.LongWait):
  1889  		c.Fatalf("state not opened")
  1890  	}
  1891  	s.waitStopped(c, state.JobManageEnviron, a, done)
  1892  	c.Assert(s.fakeEnsureMongo.EnsureCount, gc.Equals, 1)
  1893  	c.Assert(s.fakeEnsureMongo.InitiateCount, gc.Equals, 1)
  1894  }
  1895  
  1896  func (s *MachineSuite) TestMachineAgentSetsPrepareRestore(c *gc.C) {
  1897  	// Start the machine agent.
  1898  	m, _, _ := s.primeAgent(c, version.Current, state.JobHostUnits)
  1899  	a := s.newAgent(c, m)
  1900  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1901  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1902  	c.Check(a.IsRestorePreparing(), jc.IsFalse)
  1903  	c.Check(a.IsRestoreRunning(), jc.IsFalse)
  1904  	err := a.PrepareRestore()
  1905  	c.Assert(err, jc.ErrorIsNil)
  1906  	c.Assert(a.IsRestorePreparing(), jc.IsTrue)
  1907  	c.Assert(a.IsRestoreRunning(), jc.IsFalse)
  1908  	err = a.PrepareRestore()
  1909  	c.Assert(err, gc.ErrorMatches, "already in restore mode")
  1910  }
  1911  
  1912  func (s *MachineSuite) TestMachineAgentSetsRestoreInProgress(c *gc.C) {
  1913  	// Start the machine agent.
  1914  	m, _, _ := s.primeAgent(c, version.Current, state.JobHostUnits)
  1915  	a := s.newAgent(c, m)
  1916  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1917  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1918  	c.Check(a.IsRestorePreparing(), jc.IsFalse)
  1919  	c.Check(a.IsRestoreRunning(), jc.IsFalse)
  1920  	err := a.PrepareRestore()
  1921  	c.Assert(err, jc.ErrorIsNil)
  1922  	c.Assert(a.IsRestorePreparing(), jc.IsTrue)
  1923  	err = a.BeginRestore()
  1924  	c.Assert(err, jc.ErrorIsNil)
  1925  	c.Assert(a.IsRestoreRunning(), jc.IsTrue)
  1926  	err = a.BeginRestore()
  1927  	c.Assert(err, gc.ErrorMatches, "already restoring")
  1928  }
  1929  
  1930  func (s *MachineSuite) TestMachineAgentRestoreRequiresPrepare(c *gc.C) {
  1931  	// Start the machine agent.
  1932  	m, _, _ := s.primeAgent(c, version.Current, state.JobHostUnits)
  1933  	a := s.newAgent(c, m)
  1934  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1935  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1936  	c.Check(a.IsRestorePreparing(), jc.IsFalse)
  1937  	c.Check(a.IsRestoreRunning(), jc.IsFalse)
  1938  	err := a.BeginRestore()
  1939  	c.Assert(err, gc.ErrorMatches, "not in restore mode, cannot begin restoration")
  1940  	c.Assert(a.IsRestoreRunning(), jc.IsFalse)
  1941  }
  1942  
  1943  func (s *MachineSuite) TestNewEnvironmentStartsNewWorkers(c *gc.C) {
  1944  	_, closer := s.setUpNewEnvironment(c)
  1945  	defer closer()
  1946  	expectedWorkers, closer := s.setUpAgent(c)
  1947  	defer closer()
  1948  
  1949  	r1 := s.singularRecord.nextRunner(c)
  1950  	workers := r1.waitForWorker(c, "firewaller")
  1951  	c.Assert(workers, jc.SameContents, expectedWorkers)
  1952  }
  1953  
  1954  func (s *MachineSuite) TestNewStorageWorkerIsScopedToNewEnviron(c *gc.C) {
  1955  	st, closer := s.setUpNewEnvironment(c)
  1956  	defer closer()
  1957  
  1958  	// Check that newStorageWorker is called and the environ tag is scoped to
  1959  	// that of the new environment tag.
  1960  	started := make(chan struct{})
  1961  	newWorker := func(
  1962  		scope names.Tag,
  1963  		storageDir string,
  1964  		_ storageprovisioner.VolumeAccessor,
  1965  		_ storageprovisioner.FilesystemAccessor,
  1966  		_ storageprovisioner.LifecycleManager,
  1967  		_ storageprovisioner.EnvironAccessor,
  1968  		_ storageprovisioner.MachineAccessor,
  1969  		_ storageprovisioner.StatusSetter,
  1970  		_ clock.Clock,
  1971  	) worker.Worker {
  1972  		// storageDir is empty for environ storage provisioners
  1973  		if storageDir == "" {
  1974  			// If this is the worker for the new environment,
  1975  			// close the channel.
  1976  			if scope == st.EnvironTag() {
  1977  				close(started)
  1978  			}
  1979  		}
  1980  		return worker.NewNoOpWorker()
  1981  	}
  1982  	s.PatchValue(&newStorageWorker, newWorker)
  1983  
  1984  	_, closer = s.setUpAgent(c)
  1985  	defer closer()
  1986  
  1987  	// Wait for newStorageWorker to be started.
  1988  	select {
  1989  	case <-started:
  1990  	case <-time.After(coretesting.LongWait):
  1991  		c.Fatalf("timeout while waiting for storage worker to start")
  1992  	}
  1993  }
  1994  
  1995  func (s *MachineSuite) setUpNewEnvironment(c *gc.C) (newSt *state.State, closer func()) {
  1996  	// Create a new environment, tests can now watch if workers start for it.
  1997  	newSt = s.Factory.MakeEnvironment(c, &factory.EnvParams{
  1998  		ConfigAttrs: map[string]interface{}{
  1999  			"state-server": false,
  2000  		},
  2001  		Prepare: true,
  2002  	})
  2003  	return newSt, func() {
  2004  		newSt.Close()
  2005  	}
  2006  }
  2007  
  2008  func (s *MachineSuite) setUpAgent(c *gc.C) (expectedWorkers []string, closer func()) {
  2009  	expectedWorkers = make([]string, 0, len(perEnvSingularWorkers)+1)
  2010  	for _, w := range perEnvSingularWorkers {
  2011  		expectedWorkers = append(expectedWorkers, w)
  2012  		if w == "environ-provisioner" {
  2013  			expectedWorkers = append(expectedWorkers, "environ-storageprovisioner")
  2014  		}
  2015  	}
  2016  	s.PatchValue(&watcher.Period, 100*time.Millisecond)
  2017  
  2018  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
  2019  	a := s.newAgent(c, m)
  2020  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  2021  
  2022  	_ = s.singularRecord.nextRunner(c) // Don't care about this one for this test.
  2023  
  2024  	// Wait for the workers for the initial env to start. The
  2025  	// firewaller is the last worker started for a new environment.
  2026  	r0 := s.singularRecord.nextRunner(c)
  2027  	workers := r0.waitForWorker(c, "firewaller")
  2028  	c.Assert(workers, jc.SameContents, expectedWorkers)
  2029  
  2030  	return expectedWorkers, func() {
  2031  		c.Check(a.Stop(), jc.ErrorIsNil)
  2032  	}
  2033  }
  2034  
  2035  func (s *MachineSuite) TestReplicasetInitiation(c *gc.C) {
  2036  	if runtime.GOOS == "windows" {
  2037  		c.Skip("state servers on windows aren't supported")
  2038  	}
  2039  
  2040  	s.fakeEnsureMongo.ReplicasetInitiated = false
  2041  
  2042  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
  2043  	a := s.newAgent(c, m)
  2044  	agentConfig := a.CurrentConfig()
  2045  
  2046  	err := a.ensureMongoServer(agentConfig)
  2047  	c.Assert(err, jc.ErrorIsNil)
  2048  
  2049  	c.Assert(s.fakeEnsureMongo.EnsureCount, gc.Equals, 1)
  2050  	c.Assert(s.fakeEnsureMongo.InitiateCount, gc.Equals, 1)
  2051  }
  2052  
  2053  func (s *MachineSuite) TestReplicasetAlreadyInitiated(c *gc.C) {
  2054  	if runtime.GOOS == "windows" {
  2055  		c.Skip("state servers on windows aren't supported")
  2056  	}
  2057  
  2058  	s.fakeEnsureMongo.ReplicasetInitiated = true
  2059  
  2060  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
  2061  	a := s.newAgent(c, m)
  2062  	agentConfig := a.CurrentConfig()
  2063  
  2064  	err := a.ensureMongoServer(agentConfig)
  2065  	c.Assert(err, jc.ErrorIsNil)
  2066  
  2067  	c.Assert(s.fakeEnsureMongo.EnsureCount, gc.Equals, 1)
  2068  	c.Assert(s.fakeEnsureMongo.InitiateCount, gc.Equals, 0)
  2069  }
  2070  
  2071  func (s *MachineSuite) TestReplicasetInitForNewStateServer(c *gc.C) {
  2072  	if runtime.GOOS == "windows" {
  2073  		c.Skip("state servers on windows aren't supported")
  2074  	}
  2075  
  2076  	s.fakeEnsureMongo.ServiceInstalled = false
  2077  	s.fakeEnsureMongo.ReplicasetInitiated = true
  2078  
  2079  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
  2080  	a := s.newAgent(c, m)
  2081  	agentConfig := a.CurrentConfig()
  2082  
  2083  	err := a.ensureMongoServer(agentConfig)
  2084  	c.Assert(err, jc.ErrorIsNil)
  2085  
  2086  	c.Assert(s.fakeEnsureMongo.EnsureCount, gc.Equals, 1)
  2087  	c.Assert(s.fakeEnsureMongo.InitiateCount, gc.Equals, 0)
  2088  }
  2089  
  2090  // MachineWithCharmsSuite provides infrastructure for tests which need to
  2091  // work with charms.
  2092  type MachineWithCharmsSuite struct {
  2093  	commonMachineSuite
  2094  	charmtesting.CharmSuite
  2095  
  2096  	machine *state.Machine
  2097  }
  2098  
  2099  func (s *MachineWithCharmsSuite) SetUpSuite(c *gc.C) {
  2100  	s.commonMachineSuite.SetUpSuite(c)
  2101  	s.CharmSuite.SetUpSuite(c, &s.commonMachineSuite.JujuConnSuite)
  2102  }
  2103  
  2104  func (s *MachineWithCharmsSuite) TearDownSuite(c *gc.C) {
  2105  	s.CharmSuite.TearDownSuite(c)
  2106  	s.commonMachineSuite.TearDownSuite(c)
  2107  }
  2108  
  2109  func (s *MachineWithCharmsSuite) SetUpTest(c *gc.C) {
  2110  	s.commonMachineSuite.SetUpTest(c)
  2111  	s.CharmSuite.SetUpTest(c)
  2112  }
  2113  
  2114  func (s *MachineWithCharmsSuite) TearDownTest(c *gc.C) {
  2115  	s.CharmSuite.TearDownTest(c)
  2116  	s.commonMachineSuite.TearDownTest(c)
  2117  }
  2118  
  2119  func (s *MachineWithCharmsSuite) TestManageEnvironRunsCharmRevisionUpdater(c *gc.C) {
  2120  	m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron)
  2121  
  2122  	s.SetupScenario(c)
  2123  
  2124  	a := s.newAgent(c, m)
  2125  	go func() {
  2126  		c.Check(a.Run(nil), jc.ErrorIsNil)
  2127  	}()
  2128  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  2129  
  2130  	checkRevision := func() bool {
  2131  		curl := charm.MustParseURL("cs:quantal/mysql")
  2132  		placeholder, err := s.State.LatestPlaceholderCharm(curl)
  2133  		return err == nil && placeholder.String() == curl.WithRevision(23).String()
  2134  	}
  2135  	success := false
  2136  	for attempt := coretesting.LongAttempt.Start(); attempt.Next(); {
  2137  		if success = checkRevision(); success {
  2138  			break
  2139  		}
  2140  	}
  2141  	c.Assert(success, jc.IsTrue)
  2142  }
  2143  
  2144  type mongoSuite struct {
  2145  	coretesting.BaseSuite
  2146  }
  2147  
  2148  func (s *mongoSuite) TestStateWorkerDialSetsWriteMajority(c *gc.C) {
  2149  	s.testStateWorkerDialSetsWriteMajority(c, true)
  2150  }
  2151  
  2152  func (s *mongoSuite) TestStateWorkerDialDoesNotSetWriteMajorityWithoutReplsetConfig(c *gc.C) {
  2153  	s.testStateWorkerDialSetsWriteMajority(c, false)
  2154  }
  2155  
  2156  func (s *mongoSuite) testStateWorkerDialSetsWriteMajority(c *gc.C, configureReplset bool) {
  2157  	inst := gitjujutesting.MgoInstance{
  2158  		EnableJournal: true,
  2159  		Params:        []string{"--replSet", "juju"},
  2160  	}
  2161  	err := inst.Start(coretesting.Certs)
  2162  	c.Assert(err, jc.ErrorIsNil)
  2163  	defer inst.Destroy()
  2164  
  2165  	var expectedWMode string
  2166  	dialOpts := stateWorkerDialOpts
  2167  	if configureReplset {
  2168  		info := inst.DialInfo()
  2169  		args := peergrouper.InitiateMongoParams{
  2170  			DialInfo:       info,
  2171  			MemberHostPort: inst.Addr(),
  2172  		}
  2173  		err = peergrouper.MaybeInitiateMongoServer(args)
  2174  		c.Assert(err, jc.ErrorIsNil)
  2175  		expectedWMode = "majority"
  2176  	} else {
  2177  		dialOpts.Direct = true
  2178  	}
  2179  
  2180  	mongoInfo := mongo.Info{
  2181  		Addrs:  []string{inst.Addr()},
  2182  		CACert: coretesting.CACert,
  2183  	}
  2184  	session, err := mongo.DialWithInfo(mongoInfo, dialOpts)
  2185  	c.Assert(err, jc.ErrorIsNil)
  2186  	defer session.Close()
  2187  
  2188  	safe := session.Safe()
  2189  	c.Assert(safe, gc.NotNil)
  2190  	c.Assert(safe.WMode, gc.Equals, expectedWMode)
  2191  	c.Assert(safe.J, jc.IsTrue) // always enabled
  2192  }
  2193  
  2194  type shouldWriteProxyFilesSuite struct {
  2195  	coretesting.BaseSuite
  2196  }
  2197  
  2198  var _ = gc.Suite(&shouldWriteProxyFilesSuite{})
  2199  
  2200  func (s *shouldWriteProxyFilesSuite) TestAll(c *gc.C) {
  2201  	tests := []struct {
  2202  		description  string
  2203  		providerType string
  2204  		machineId    string
  2205  		expect       bool
  2206  	}{{
  2207  		description:  "local provider machine 0 must not write",
  2208  		providerType: "local",
  2209  		machineId:    "0",
  2210  		expect:       false,
  2211  	}, {
  2212  		description:  "local provider other machine must write 1",
  2213  		providerType: "local",
  2214  		machineId:    "0/kvm/0",
  2215  		expect:       true,
  2216  	}, {
  2217  		description:  "local provider other machine must write 2",
  2218  		providerType: "local",
  2219  		machineId:    "123",
  2220  		expect:       true,
  2221  	}, {
  2222  		description:  "other provider machine 0 must write",
  2223  		providerType: "anything",
  2224  		machineId:    "0",
  2225  		expect:       true,
  2226  	}, {
  2227  		description:  "other provider other machine must write 1",
  2228  		providerType: "dummy",
  2229  		machineId:    "0/kvm/0",
  2230  		expect:       true,
  2231  	}, {
  2232  		description:  "other provider other machine must write 2",
  2233  		providerType: "blahblahblah",
  2234  		machineId:    "123",
  2235  		expect:       true,
  2236  	}}
  2237  	for i, test := range tests {
  2238  		c.Logf("test %d: %s", i, test.description)
  2239  		mockConf := &mockAgentConfig{
  2240  			providerType: test.providerType,
  2241  			tag:          names.NewMachineTag(test.machineId),
  2242  		}
  2243  		c.Check(shouldWriteProxyFiles(mockConf), gc.Equals, test.expect)
  2244  	}
  2245  }
  2246  
  2247  type mockAgentConfig struct {
  2248  	agent.Config
  2249  	providerType string
  2250  	tag          names.Tag
  2251  }
  2252  
  2253  func (m *mockAgentConfig) Tag() names.Tag {
  2254  	return m.tag
  2255  }
  2256  
  2257  func (m *mockAgentConfig) Value(key string) string {
  2258  	if key == agent.ProviderType {
  2259  		return m.providerType
  2260  	}
  2261  	return ""
  2262  }
  2263  
  2264  type singularRunnerRecord struct {
  2265  	runnerC chan *fakeSingularRunner
  2266  }
  2267  
  2268  func newSingularRunnerRecord() *singularRunnerRecord {
  2269  	return &singularRunnerRecord{
  2270  		runnerC: make(chan *fakeSingularRunner, 5),
  2271  	}
  2272  }
  2273  
  2274  func (r *singularRunnerRecord) newSingularRunner(runner worker.Runner, conn singular.Conn) (worker.Runner, error) {
  2275  	sr, err := singular.New(runner, conn)
  2276  	if err != nil {
  2277  		return nil, err
  2278  	}
  2279  	fakeRunner := &fakeSingularRunner{
  2280  		Runner: sr,
  2281  		startC: make(chan string, 64),
  2282  	}
  2283  	r.runnerC <- fakeRunner
  2284  	return fakeRunner, nil
  2285  }
  2286  
  2287  // nextRunner blocks until a new singular runner is created.
  2288  func (r *singularRunnerRecord) nextRunner(c *gc.C) *fakeSingularRunner {
  2289  	for {
  2290  		select {
  2291  		case r := <-r.runnerC:
  2292  			return r
  2293  		case <-time.After(coretesting.LongWait):
  2294  			c.Fatal("timed out waiting for singular runner to be created")
  2295  		}
  2296  	}
  2297  }
  2298  
  2299  type fakeSingularRunner struct {
  2300  	worker.Runner
  2301  	startC chan string
  2302  }
  2303  
  2304  func (r *fakeSingularRunner) StartWorker(name string, start func() (worker.Worker, error)) error {
  2305  	r.startC <- name
  2306  	return r.Runner.StartWorker(name, start)
  2307  }
  2308  
  2309  // waitForWorker waits for a given worker to be started, returning all
  2310  // workers started while waiting.
  2311  func (r *fakeSingularRunner) waitForWorker(c *gc.C, target string) []string {
  2312  	var seen []string
  2313  	timeout := time.After(coretesting.LongWait)
  2314  	for {
  2315  		select {
  2316  		case workerName := <-r.startC:
  2317  			seen = append(seen, workerName)
  2318  			if workerName == target {
  2319  				return seen
  2320  			}
  2321  		case <-timeout:
  2322  			c.Fatal("timed out waiting for " + target)
  2323  		}
  2324  	}
  2325  }
  2326  
  2327  // waitForWorkers waits for a given worker to be started, returning all
  2328  // workers started while waiting.
  2329  func (r *fakeSingularRunner) waitForWorkers(c *gc.C, targets []string) []string {
  2330  	var seen []string
  2331  	seenTargets := make(map[string]bool)
  2332  	numSeenTargets := 0
  2333  	timeout := time.After(coretesting.LongWait)
  2334  	for {
  2335  		select {
  2336  		case workerName := <-r.startC:
  2337  			if seenTargets[workerName] == true {
  2338  				c.Fatal("worker started twice: " + workerName)
  2339  			}
  2340  			seenTargets[workerName] = true
  2341  			numSeenTargets++
  2342  			seen = append(seen, workerName)
  2343  			if numSeenTargets == len(targets) {
  2344  				return seen
  2345  			}
  2346  		case <-timeout:
  2347  			c.Fatalf("timed out waiting for %v", targets)
  2348  		}
  2349  	}
  2350  }
  2351  
  2352  type mockMetricAPI struct {
  2353  	stop          chan struct{}
  2354  	cleanUpCalled chan struct{}
  2355  	sendCalled    chan struct{}
  2356  }
  2357  
  2358  func newMockMetricAPI() *mockMetricAPI {
  2359  	return &mockMetricAPI{
  2360  		stop:          make(chan struct{}),
  2361  		cleanUpCalled: make(chan struct{}),
  2362  		sendCalled:    make(chan struct{}),
  2363  	}
  2364  }
  2365  
  2366  func (m *mockMetricAPI) CleanupOldMetrics() error {
  2367  	go func() {
  2368  		select {
  2369  		case m.cleanUpCalled <- struct{}{}:
  2370  		case <-m.stop:
  2371  			break
  2372  		}
  2373  	}()
  2374  	return nil
  2375  }
  2376  
  2377  func (m *mockMetricAPI) SendMetrics() error {
  2378  	go func() {
  2379  		select {
  2380  		case m.sendCalled <- struct{}{}:
  2381  		case <-m.stop:
  2382  			break
  2383  		}
  2384  	}()
  2385  	return nil
  2386  }
  2387  
  2388  func (m *mockMetricAPI) SendCalled() <-chan struct{} {
  2389  	return m.sendCalled
  2390  }
  2391  
  2392  func (m *mockMetricAPI) CleanupCalled() <-chan struct{} {
  2393  	return m.cleanUpCalled
  2394  }
  2395  
  2396  func (m *mockMetricAPI) Stop() {
  2397  	close(m.stop)
  2398  }
  2399  
  2400  func mkdtemp(prefix string) string {
  2401  	d, err := ioutil.TempDir("", prefix)
  2402  	if err != nil {
  2403  		panic(err)
  2404  	}
  2405  	return d
  2406  }
  2407  
  2408  func mktemp(prefix string, content string) string {
  2409  	f, err := ioutil.TempFile("", prefix)
  2410  	if err != nil {
  2411  		panic(err)
  2412  	}
  2413  	_, err = f.WriteString(content)
  2414  	if err != nil {
  2415  		panic(err)
  2416  	}
  2417  	f.Close()
  2418  	return f.Name()
  2419  }
  2420  
  2421  type mockLoopDeviceManager struct {
  2422  	detachLoopDevicesArgRootfs string
  2423  	detachLoopDevicesArgPrefix string
  2424  }
  2425  
  2426  func (m *mockLoopDeviceManager) DetachLoopDevices(rootfs, prefix string) error {
  2427  	m.detachLoopDevicesArgRootfs = rootfs
  2428  	m.detachLoopDevicesArgPrefix = prefix
  2429  	return nil
  2430  }