github.com/mwhudson/juju@v0.0.0-20160512215208-90ff01f3497f/cmd/jujud/agent/machine_test.go (about)

     1  // Copyright 2012-2016 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"
    15  	"time"
    16  
    17  	"github.com/juju/cmd"
    18  	"github.com/juju/cmd/cmdtesting"
    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"
    24  	"github.com/juju/utils/arch"
    25  	"github.com/juju/utils/series"
    26  	"github.com/juju/utils/set"
    27  	"github.com/juju/utils/ssh"
    28  	sshtesting "github.com/juju/utils/ssh/testing"
    29  	"github.com/juju/utils/symlink"
    30  	"github.com/juju/version"
    31  	gc "gopkg.in/check.v1"
    32  	"gopkg.in/juju/charm.v6-unstable"
    33  	"gopkg.in/juju/charmrepo.v2-unstable"
    34  	"gopkg.in/natefinch/lumberjack.v2"
    35  
    36  	"github.com/juju/juju/agent"
    37  	"github.com/juju/juju/api"
    38  	apideployer "github.com/juju/juju/api/deployer"
    39  	"github.com/juju/juju/api/imagemetadata"
    40  	apimachiner "github.com/juju/juju/api/machiner"
    41  	charmtesting "github.com/juju/juju/apiserver/charmrevisionupdater/testing"
    42  	"github.com/juju/juju/apiserver/params"
    43  	"github.com/juju/juju/cert"
    44  	agenttesting "github.com/juju/juju/cmd/jujud/agent/testing"
    45  	cmdutil "github.com/juju/juju/cmd/jujud/util"
    46  	lxctesting "github.com/juju/juju/container/lxc/testing"
    47  	envtesting "github.com/juju/juju/environs/testing"
    48  	"github.com/juju/juju/feature"
    49  	"github.com/juju/juju/instance"
    50  	"github.com/juju/juju/juju"
    51  	jujutesting "github.com/juju/juju/juju/testing"
    52  	"github.com/juju/juju/mongo"
    53  	"github.com/juju/juju/mongo/mongotest"
    54  	"github.com/juju/juju/network"
    55  	"github.com/juju/juju/provider/dummy"
    56  	"github.com/juju/juju/service/upstart"
    57  	"github.com/juju/juju/state"
    58  	"github.com/juju/juju/state/watcher"
    59  	"github.com/juju/juju/status"
    60  	"github.com/juju/juju/storage"
    61  	coretesting "github.com/juju/juju/testing"
    62  	"github.com/juju/juju/tools"
    63  	jujuversion "github.com/juju/juju/version"
    64  	"github.com/juju/juju/worker"
    65  	"github.com/juju/juju/worker/authenticationworker"
    66  	"github.com/juju/juju/worker/certupdater"
    67  	"github.com/juju/juju/worker/deployer"
    68  	"github.com/juju/juju/worker/diskmanager"
    69  	"github.com/juju/juju/worker/instancepoller"
    70  	"github.com/juju/juju/worker/logsender"
    71  	"github.com/juju/juju/worker/machiner"
    72  	"github.com/juju/juju/worker/mongoupgrader"
    73  	"github.com/juju/juju/worker/peergrouper"
    74  	"github.com/juju/juju/worker/resumer"
    75  	"github.com/juju/juju/worker/singular"
    76  	"github.com/juju/juju/worker/storageprovisioner"
    77  	"github.com/juju/juju/worker/upgrader"
    78  )
    79  
    80  var (
    81  	_ = gc.Suite(&MachineSuite{})
    82  	_ = gc.Suite(&MachineWithCharmsSuite{})
    83  	_ = gc.Suite(&mongoSuite{})
    84  )
    85  
    86  type commonMachineSuite struct {
    87  	singularRecord *singularRunnerRecord
    88  	lxctesting.TestSuite
    89  	fakeEnsureMongo *agenttesting.FakeEnsureMongo
    90  	AgentSuite
    91  }
    92  
    93  func (s *commonMachineSuite) SetUpSuite(c *gc.C) {
    94  	s.AgentSuite.SetUpSuite(c)
    95  	s.TestSuite.SetUpSuite(c)
    96  	s.AgentSuite.PatchValue(&jujuversion.Current, coretesting.FakeVersionNumber)
    97  	s.AgentSuite.PatchValue(&stateWorkerDialOpts, mongotest.DialOpts())
    98  }
    99  
   100  func (s *commonMachineSuite) TearDownSuite(c *gc.C) {
   101  	s.TestSuite.TearDownSuite(c)
   102  	s.AgentSuite.TearDownSuite(c)
   103  }
   104  
   105  func (s *commonMachineSuite) SetUpTest(c *gc.C) {
   106  	s.AgentSuite.SetUpTest(c)
   107  	s.TestSuite.SetUpTest(c)
   108  	s.AgentSuite.PatchValue(&charmrepo.CacheDir, c.MkDir())
   109  
   110  	// Patch ssh user to avoid touching ~ubuntu/.ssh/authorized_keys.
   111  	s.AgentSuite.PatchValue(&authenticationworker.SSHUser, "")
   112  
   113  	testpath := c.MkDir()
   114  	s.AgentSuite.PatchEnvPathPrepend(testpath)
   115  	// mock out the start method so we can fake install services without sudo
   116  	fakeCmd(filepath.Join(testpath, "start"))
   117  	fakeCmd(filepath.Join(testpath, "stop"))
   118  
   119  	s.AgentSuite.PatchValue(&upstart.InitDir, c.MkDir())
   120  
   121  	s.singularRecord = newSingularRunnerRecord()
   122  	s.AgentSuite.PatchValue(&newSingularRunner, s.singularRecord.newSingularRunner)
   123  	s.AgentSuite.PatchValue(&peergrouperNew, func(st *state.State) (worker.Worker, error) {
   124  		return newDummyWorker(), nil
   125  	})
   126  
   127  	s.fakeEnsureMongo = agenttesting.InstallFakeEnsureMongo(s)
   128  }
   129  
   130  func (s *commonMachineSuite) assertChannelActive(c *gc.C, aChannel chan struct{}, intent string) {
   131  	// Wait for channel to be active.
   132  	select {
   133  	case <-aChannel:
   134  	case <-time.After(coretesting.LongWait):
   135  		c.Fatalf("timeout while waiting for %v", intent)
   136  	}
   137  }
   138  
   139  func (s *commonMachineSuite) assertChannelInactive(c *gc.C, aChannel chan struct{}, intent string) {
   140  	// Now make sure the channel is not active.
   141  	select {
   142  	case <-aChannel:
   143  		c.Fatalf("%v unexpectedly", intent)
   144  	case <-time.After(startWorkerWait):
   145  	}
   146  }
   147  
   148  func fakeCmd(path string) {
   149  	err := ioutil.WriteFile(path, []byte("#!/bin/bash --norc\nexit 0"), 0755)
   150  	if err != nil {
   151  		panic(err)
   152  	}
   153  }
   154  
   155  func (s *commonMachineSuite) TearDownTest(c *gc.C) {
   156  	s.TestSuite.TearDownTest(c)
   157  	s.AgentSuite.TearDownTest(c)
   158  }
   159  
   160  // primeAgent adds a new Machine to run the given jobs, and sets up the
   161  // machine agent's directory.  It returns the new machine, the
   162  // agent's configuration and the tools currently running.
   163  func (s *commonMachineSuite) primeAgent(c *gc.C, jobs ...state.MachineJob) (m *state.Machine, agentConfig agent.ConfigSetterWriter, tools *tools.Tools) {
   164  	vers := version.Binary{
   165  		Number: jujuversion.Current,
   166  		Arch:   arch.HostArch(),
   167  		Series: series.HostSeries(),
   168  	}
   169  	return s.primeAgentVersion(c, vers, jobs...)
   170  }
   171  
   172  // primeAgentVersion is similar to primeAgent, but permits the
   173  // caller to specify the version.Binary to prime with.
   174  func (s *commonMachineSuite) primeAgentVersion(c *gc.C, vers version.Binary, jobs ...state.MachineJob) (m *state.Machine, agentConfig agent.ConfigSetterWriter, tools *tools.Tools) {
   175  	m, err := s.State.AddMachine("quantal", jobs...)
   176  	c.Assert(err, jc.ErrorIsNil)
   177  	return s.primeAgentWithMachine(c, m, vers)
   178  }
   179  
   180  func (s *commonMachineSuite) primeAgentWithMachine(c *gc.C, m *state.Machine, vers version.Binary) (*state.Machine, agent.ConfigSetterWriter, *tools.Tools) {
   181  	pinger, err := m.SetAgentPresence()
   182  	c.Assert(err, jc.ErrorIsNil)
   183  	s.AddCleanup(func(c *gc.C) {
   184  		err := pinger.Stop()
   185  		c.Check(err, jc.ErrorIsNil)
   186  	})
   187  	return s.configureMachine(c, m.Id(), vers)
   188  }
   189  
   190  func (s *commonMachineSuite) configureMachine(c *gc.C, machineId string, vers version.Binary) (
   191  	machine *state.Machine, agentConfig agent.ConfigSetterWriter, tools *tools.Tools,
   192  ) {
   193  	m, err := s.State.Machine(machineId)
   194  	c.Assert(err, jc.ErrorIsNil)
   195  
   196  	// Add a machine and ensure it is provisioned.
   197  	inst, md := jujutesting.AssertStartInstance(c, s.Environ, machineId)
   198  	c.Assert(m.SetProvisioned(inst.Id(), agent.BootstrapNonce, md), jc.ErrorIsNil)
   199  
   200  	// Add an address for the tests in case the initiateMongoServer
   201  	// codepath is exercised.
   202  	s.setFakeMachineAddresses(c, m)
   203  
   204  	// Set up the new machine.
   205  	err = m.SetAgentVersion(vers)
   206  	c.Assert(err, jc.ErrorIsNil)
   207  	err = m.SetPassword(initialMachinePassword)
   208  	c.Assert(err, jc.ErrorIsNil)
   209  	tag := m.Tag()
   210  	if m.IsManager() {
   211  		err = m.SetMongoPassword(initialMachinePassword)
   212  		c.Assert(err, jc.ErrorIsNil)
   213  		agentConfig, tools = s.PrimeStateAgentVersion(c, tag, initialMachinePassword, vers)
   214  		info, ok := agentConfig.StateServingInfo()
   215  		c.Assert(ok, jc.IsTrue)
   216  		ssi := cmdutil.ParamsStateServingInfoToStateStateServingInfo(info)
   217  		err = s.State.SetStateServingInfo(ssi)
   218  		c.Assert(err, jc.ErrorIsNil)
   219  	} else {
   220  		agentConfig, tools = s.PrimeAgentVersion(c, tag, initialMachinePassword, vers)
   221  	}
   222  	err = agentConfig.Write()
   223  	c.Assert(err, jc.ErrorIsNil)
   224  	return m, agentConfig, tools
   225  }
   226  
   227  func NewTestMachineAgentFactory(
   228  	agentConfWriter AgentConfigWriter,
   229  	bufferedLogs logsender.LogRecordCh,
   230  	rootDir string,
   231  ) func(string) *MachineAgent {
   232  	return func(machineId string) *MachineAgent {
   233  		return NewMachineAgent(
   234  			machineId,
   235  			agentConfWriter,
   236  			bufferedLogs,
   237  			worker.NewRunner(cmdutil.IsFatal, cmdutil.MoreImportant, worker.RestartDelay),
   238  			&mockLoopDeviceManager{},
   239  			rootDir,
   240  		)
   241  	}
   242  }
   243  
   244  // newAgent returns a new MachineAgent instance
   245  func (s *commonMachineSuite) newAgent(c *gc.C, m *state.Machine) *MachineAgent {
   246  	agentConf := agentConf{dataDir: s.DataDir()}
   247  	agentConf.ReadConfig(names.NewMachineTag(m.Id()).String())
   248  	machineAgentFactory := NewTestMachineAgentFactory(&agentConf, nil, c.MkDir())
   249  	return machineAgentFactory(m.Id())
   250  }
   251  
   252  func (s *MachineSuite) TestParseSuccess(c *gc.C) {
   253  	create := func() (cmd.Command, AgentConf) {
   254  		agentConf := agentConf{dataDir: s.DataDir()}
   255  		a := NewMachineAgentCmd(
   256  			nil,
   257  			NewTestMachineAgentFactory(&agentConf, nil, c.MkDir()),
   258  			&agentConf,
   259  			&agentConf,
   260  		)
   261  		a.(*machineAgentCmd).logToStdErr = true
   262  
   263  		return a, &agentConf
   264  	}
   265  	a := CheckAgentCommand(c, create, []string{"--machine-id", "42"})
   266  	c.Assert(a.(*machineAgentCmd).machineId, gc.Equals, "42")
   267  }
   268  
   269  type MachineSuite struct {
   270  	commonMachineSuite
   271  }
   272  
   273  var perEnvSingularWorkers = []string{
   274  	"cleaner",
   275  	"minunitsworker",
   276  	"addresserworker",
   277  	"environ-provisioner",
   278  	"charm-revision-updater",
   279  	"discoverspaces",
   280  	"instancepoller",
   281  	"firewaller",
   282  	"unitassigner",
   283  }
   284  
   285  const initialMachinePassword = "machine-password-1234567890"
   286  
   287  func (s *MachineSuite) SetUpTest(c *gc.C) {
   288  	s.commonMachineSuite.SetUpTest(c)
   289  	// Most of these tests normally finish sub-second on a fast machine.
   290  	// If any given test hits a minute, we have almost certainly become
   291  	// wedged, so dump the logs.
   292  	coretesting.DumpTestLogsAfter(time.Minute, c, s)
   293  }
   294  
   295  func (s *MachineSuite) TestParseNonsense(c *gc.C) {
   296  	for _, args := range [][]string{
   297  		{},
   298  		{"--machine-id", "-4004"},
   299  	} {
   300  		var agentConf agentConf
   301  		err := ParseAgentCommand(&machineAgentCmd{agentInitializer: &agentConf}, args)
   302  		c.Assert(err, gc.ErrorMatches, "--machine-id option must be set, and expects a non-negative integer")
   303  	}
   304  }
   305  
   306  func (s *MachineSuite) TestParseUnknown(c *gc.C) {
   307  	var agentConf agentConf
   308  	a := &machineAgentCmd{agentInitializer: &agentConf}
   309  	err := ParseAgentCommand(a, []string{"--machine-id", "42", "blistering barnacles"})
   310  	c.Assert(err, gc.ErrorMatches, `unrecognized args: \["blistering barnacles"\]`)
   311  }
   312  
   313  func (s *MachineSuite) TestRunInvalidMachineId(c *gc.C) {
   314  	c.Skip("agents don't yet distinguish between temporary and permanent errors")
   315  	m, _, _ := s.primeAgent(c, state.JobHostUnits)
   316  	err := s.newAgent(c, m).Run(nil)
   317  	c.Assert(err, gc.ErrorMatches, "some error")
   318  }
   319  
   320  func (s *MachineSuite) TestUseLumberjack(c *gc.C) {
   321  	ctx := cmdtesting.Context(c)
   322  	agentConf := FakeAgentConfig{}
   323  
   324  	a := NewMachineAgentCmd(
   325  		ctx,
   326  		NewTestMachineAgentFactory(&agentConf, nil, c.MkDir()),
   327  		agentConf,
   328  		agentConf,
   329  	)
   330  	// little hack to set the data that Init expects to already be set
   331  	a.(*machineAgentCmd).machineId = "42"
   332  
   333  	err := a.Init(nil)
   334  	c.Assert(err, gc.IsNil)
   335  
   336  	l, ok := ctx.Stderr.(*lumberjack.Logger)
   337  	c.Assert(ok, jc.IsTrue)
   338  	c.Check(l.MaxAge, gc.Equals, 0)
   339  	c.Check(l.MaxBackups, gc.Equals, 2)
   340  	c.Check(l.Filename, gc.Equals, filepath.FromSlash("/var/log/juju/machine-42.log"))
   341  	c.Check(l.MaxSize, gc.Equals, 300)
   342  }
   343  
   344  func (s *MachineSuite) TestDontUseLumberjack(c *gc.C) {
   345  	ctx := cmdtesting.Context(c)
   346  	agentConf := FakeAgentConfig{}
   347  
   348  	a := NewMachineAgentCmd(
   349  		ctx,
   350  		NewTestMachineAgentFactory(&agentConf, nil, c.MkDir()),
   351  		agentConf,
   352  		agentConf,
   353  	)
   354  	// little hack to set the data that Init expects to already be set
   355  	a.(*machineAgentCmd).machineId = "42"
   356  
   357  	// set the value that normally gets set by the flag parsing
   358  	a.(*machineAgentCmd).logToStdErr = true
   359  
   360  	err := a.Init(nil)
   361  	c.Assert(err, gc.IsNil)
   362  
   363  	_, ok := ctx.Stderr.(*lumberjack.Logger)
   364  	c.Assert(ok, jc.IsFalse)
   365  }
   366  
   367  func (s *MachineSuite) TestRunStop(c *gc.C) {
   368  	m, ac, _ := s.primeAgent(c, state.JobHostUnits)
   369  	a := s.newAgent(c, m)
   370  	done := make(chan error)
   371  	go func() {
   372  		done <- a.Run(nil)
   373  	}()
   374  	err := a.Stop()
   375  	c.Assert(err, jc.ErrorIsNil)
   376  	c.Assert(<-done, jc.ErrorIsNil)
   377  	c.Assert(charmrepo.CacheDir, gc.Equals, filepath.Join(ac.DataDir(), "charmcache"))
   378  }
   379  
   380  func (s *MachineSuite) TestWithDeadMachine(c *gc.C) {
   381  	m, ac, _ := s.primeAgent(c, state.JobHostUnits)
   382  	err := m.EnsureDead()
   383  	c.Assert(err, jc.ErrorIsNil)
   384  	a := s.newAgent(c, m)
   385  	err = runWithTimeout(a)
   386  	c.Assert(err, jc.ErrorIsNil)
   387  
   388  	_, err = os.Stat(ac.DataDir())
   389  	c.Assert(err, jc.Satisfies, os.IsNotExist)
   390  }
   391  
   392  func (s *MachineSuite) TestWithRemovedMachine(c *gc.C) {
   393  	m, ac, _ := s.primeAgent(c, state.JobHostUnits)
   394  	err := m.EnsureDead()
   395  	c.Assert(err, jc.ErrorIsNil)
   396  	err = m.Remove()
   397  	c.Assert(err, jc.ErrorIsNil)
   398  	a := s.newAgent(c, m)
   399  	err = runWithTimeout(a)
   400  	c.Assert(err, jc.ErrorIsNil)
   401  
   402  	_, err = os.Stat(ac.DataDir())
   403  	c.Assert(err, jc.Satisfies, os.IsNotExist)
   404  }
   405  
   406  func (s *MachineSuite) TestDyingMachine(c *gc.C) {
   407  	m, _, _ := s.primeAgent(c, state.JobHostUnits)
   408  	a := s.newAgent(c, m)
   409  	done := make(chan error)
   410  	go func() {
   411  		done <- a.Run(nil)
   412  	}()
   413  	defer func() {
   414  		c.Check(a.Stop(), jc.ErrorIsNil)
   415  	}()
   416  	// Wait for configuration to be finished
   417  	<-a.WorkersStarted()
   418  	err := m.Destroy()
   419  	c.Assert(err, jc.ErrorIsNil)
   420  	select {
   421  	case err := <-done:
   422  		c.Assert(err, jc.ErrorIsNil)
   423  	case <-time.After(watcher.Period * 5 / 4):
   424  		// TODO(rog) Fix this so it doesn't wait for so long.
   425  		// https://bugs.launchpad.net/juju-core/+bug/1163983
   426  		c.Fatalf("timed out waiting for agent to terminate")
   427  	}
   428  	err = m.Refresh()
   429  	c.Assert(err, jc.ErrorIsNil)
   430  	c.Assert(m.Life(), gc.Equals, state.Dead)
   431  }
   432  
   433  func (s *MachineSuite) TestHostUnits(c *gc.C) {
   434  	m, _, _ := s.primeAgent(c, state.JobHostUnits)
   435  	a := s.newAgent(c, m)
   436  	ctx, reset := patchDeployContext(c, s.BackingState)
   437  	defer reset()
   438  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
   439  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
   440  
   441  	// check that unassigned units don't trigger any deployments.
   442  	svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   443  	u0, err := svc.AddUnit()
   444  	c.Assert(err, jc.ErrorIsNil)
   445  	u1, err := svc.AddUnit()
   446  	c.Assert(err, jc.ErrorIsNil)
   447  
   448  	ctx.waitDeployed(c)
   449  
   450  	// assign u0, check it's deployed.
   451  	err = u0.AssignToMachine(m)
   452  	c.Assert(err, jc.ErrorIsNil)
   453  	ctx.waitDeployed(c, u0.Name())
   454  
   455  	// "start the agent" for u0 to prevent short-circuited remove-on-destroy;
   456  	// check that it's kept deployed despite being Dying.
   457  	err = u0.SetAgentStatus(status.StatusIdle, "", nil)
   458  	c.Assert(err, jc.ErrorIsNil)
   459  	err = u0.Destroy()
   460  	c.Assert(err, jc.ErrorIsNil)
   461  	ctx.waitDeployed(c, u0.Name())
   462  
   463  	// add u1 to the machine, check it's deployed.
   464  	err = u1.AssignToMachine(m)
   465  	c.Assert(err, jc.ErrorIsNil)
   466  	ctx.waitDeployed(c, u0.Name(), u1.Name())
   467  
   468  	// make u0 dead; check the deployer recalls the unit and removes it from
   469  	// state.
   470  	err = u0.EnsureDead()
   471  	c.Assert(err, jc.ErrorIsNil)
   472  	ctx.waitDeployed(c, u1.Name())
   473  
   474  	// The deployer actually removes the unit just after
   475  	// removing its deployment, so we need to poll here
   476  	// until it actually happens.
   477  	for attempt := coretesting.LongAttempt.Start(); attempt.Next(); {
   478  		if !attempt.HasNext() {
   479  			c.Fatalf("timeout waiting for unit %q to be removed", u0.Name())
   480  		}
   481  		if err := u0.Refresh(); err == nil {
   482  			c.Logf("waiting unit %q to be removed...", u0.Name())
   483  			continue
   484  		} else {
   485  			c.Assert(err, jc.Satisfies, errors.IsNotFound)
   486  			break
   487  		}
   488  	}
   489  
   490  	// short-circuit-remove u1 after it's been deployed; check it's recalled
   491  	// and removed from state.
   492  	err = u1.Destroy()
   493  	c.Assert(err, jc.ErrorIsNil)
   494  	err = u1.Refresh()
   495  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   496  	ctx.waitDeployed(c)
   497  }
   498  
   499  func patchDeployContext(c *gc.C, st *state.State) (*fakeContext, func()) {
   500  	ctx := &fakeContext{
   501  		inited:   newSignal(),
   502  		deployed: make(set.Strings),
   503  	}
   504  	orig := newDeployContext
   505  	newDeployContext = func(dst *apideployer.State, agentConfig agent.Config) deployer.Context {
   506  		ctx.st = st
   507  		ctx.agentConfig = agentConfig
   508  		ctx.inited.trigger()
   509  		return ctx
   510  	}
   511  	return ctx, func() { newDeployContext = orig }
   512  }
   513  
   514  func (s *commonMachineSuite) setFakeMachineAddresses(c *gc.C, machine *state.Machine) {
   515  	addrs := network.NewAddresses("0.1.2.3")
   516  	err := machine.SetProviderAddresses(addrs...)
   517  	c.Assert(err, jc.ErrorIsNil)
   518  	// Set the addresses in the environ instance as well so that if the instance poller
   519  	// runs it won't overwrite them.
   520  	instId, err := machine.InstanceId()
   521  	c.Assert(err, jc.ErrorIsNil)
   522  	insts, err := s.Environ.Instances([]instance.Id{instId})
   523  	c.Assert(err, jc.ErrorIsNil)
   524  	dummy.SetInstanceAddresses(insts[0], addrs)
   525  }
   526  
   527  func (s *MachineSuite) TestManageModel(c *gc.C) {
   528  	usefulVersion := version.Binary{
   529  		Number: jujuversion.Current,
   530  		Arch:   arch.HostArch(),
   531  		Series: "quantal", // to match the charm created below
   532  	}
   533  	envtesting.AssertUploadFakeToolsVersions(c, s.DefaultToolsStorage, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), usefulVersion)
   534  	// Prime agent with manage networking in additon to manage model to ensure the former is ignored.
   535  	m, _, _ := s.primeAgent(c, state.JobManageModel, state.JobManageNetworking)
   536  	op := make(chan dummy.Operation, 200)
   537  	dummy.Listen(op)
   538  
   539  	a := s.newAgent(c, m)
   540  	// Make sure the agent is stopped even if the test fails.
   541  	defer a.Stop()
   542  	done := make(chan error)
   543  	go func() {
   544  		done <- a.Run(nil)
   545  	}()
   546  	c.Logf("started test agent, waiting for workers...")
   547  	r0 := s.singularRecord.nextRunner(c)
   548  	r0.waitForWorker(c, "txnpruner")
   549  
   550  	// Check that the provisioner and firewaller are alive by doing
   551  	// a rudimentary check that it responds to state changes.
   552  
   553  	// Create an exposed service, and add a unit.
   554  	charm := s.AddTestingCharm(c, "dummy")
   555  	svc := s.AddTestingService(c, "test-service", charm)
   556  	err := svc.SetExposed()
   557  	c.Assert(err, jc.ErrorIsNil)
   558  	units, err := juju.AddUnits(s.State, svc, 1, nil)
   559  	c.Assert(err, jc.ErrorIsNil)
   560  
   561  	// It should be allocated to a machine, which should then be provisioned.
   562  	c.Logf("service %q added with 1 unit, waiting for unit %q's machine to be started...", svc.Name(), units[0].Name())
   563  	c.Check(opRecvTimeout(c, s.State, op, dummy.OpStartInstance{}), gc.NotNil)
   564  	c.Logf("machine hosting unit %q started, waiting for the unit to be deployed...", units[0].Name())
   565  	s.waitProvisioned(c, units[0])
   566  
   567  	// Open a port on the unit; it should be handled by the firewaller.
   568  	c.Logf("unit %q deployed, opening port tcp/999...", units[0].Name())
   569  	err = units[0].OpenPort("tcp", 999)
   570  	c.Assert(err, jc.ErrorIsNil)
   571  	c.Check(opRecvTimeout(c, s.State, op, dummy.OpOpenPorts{}), gc.NotNil)
   572  	c.Logf("unit %q port tcp/999 opened, cleaning up...", units[0].Name())
   573  
   574  	err = a.Stop()
   575  	c.Assert(err, jc.ErrorIsNil)
   576  	select {
   577  	case err := <-done:
   578  		c.Assert(err, jc.ErrorIsNil)
   579  	case <-time.After(coretesting.LongWait):
   580  		c.Fatalf("timed out waiting for agent to terminate")
   581  	}
   582  	c.Logf("test agent stopped successfully.")
   583  }
   584  
   585  func (s *MachineSuite) TestManageModelRunsResumer(c *gc.C) {
   586  	started := newSignal()
   587  	s.AgentSuite.PatchValue(&resumer.NewResumer, func(st resumer.TransactionResumer) worker.Worker {
   588  		started.trigger()
   589  		return newDummyWorker()
   590  	})
   591  
   592  	m, _, _ := s.primeAgent(c, state.JobManageModel)
   593  	a := s.newAgent(c, m)
   594  	defer a.Stop()
   595  	go func() {
   596  		c.Check(a.Run(nil), jc.ErrorIsNil)
   597  	}()
   598  	started.assertTriggered(c, "resumer worker to start")
   599  }
   600  
   601  const startWorkerWait = 250 * time.Millisecond
   602  
   603  func (s *MachineSuite) TestManageModelRunsInstancePoller(c *gc.C) {
   604  	s.AgentSuite.PatchValue(&instancepoller.ShortPoll, 500*time.Millisecond)
   605  	usefulVersion := version.Binary{
   606  		Number: jujuversion.Current,
   607  		Arch:   arch.HostArch(),
   608  		Series: "quantal", // to match the charm created below
   609  	}
   610  	envtesting.AssertUploadFakeToolsVersions(
   611  		c, s.DefaultToolsStorage,
   612  		s.Environ.Config().AgentStream(),
   613  		s.Environ.Config().AgentStream(),
   614  		usefulVersion,
   615  	)
   616  	m, _, _ := s.primeAgent(c, state.JobManageModel)
   617  	a := s.newAgent(c, m)
   618  	defer a.Stop()
   619  	go func() {
   620  		c.Check(a.Run(nil), jc.ErrorIsNil)
   621  	}()
   622  
   623  	// Add one unit to a service;
   624  	charm := s.AddTestingCharm(c, "dummy")
   625  	svc := s.AddTestingService(c, "test-service", charm)
   626  	units, err := juju.AddUnits(s.State, svc, 1, nil)
   627  	c.Assert(err, jc.ErrorIsNil)
   628  
   629  	m, instId := s.waitProvisioned(c, units[0])
   630  	insts, err := s.Environ.Instances([]instance.Id{instId})
   631  	c.Assert(err, jc.ErrorIsNil)
   632  	addrs := network.NewAddresses("1.2.3.4")
   633  	dummy.SetInstanceAddresses(insts[0], addrs)
   634  	dummy.SetInstanceStatus(insts[0], "running")
   635  
   636  	for attempt := coretesting.LongAttempt.Start(); attempt.Next(); {
   637  		if !attempt.HasNext() {
   638  			c.Logf("final machine addresses: %#v", m.Addresses())
   639  			c.Fatalf("timed out waiting for machine to get address")
   640  		}
   641  		err := m.Refresh()
   642  		c.Assert(err, jc.ErrorIsNil)
   643  		instStatus, err := m.InstanceStatus()
   644  		c.Assert(err, jc.ErrorIsNil)
   645  		c.Logf("found status is %q %q", instStatus.Status, instStatus.Message)
   646  		if reflect.DeepEqual(m.Addresses(), addrs) && instStatus.Message == "running" {
   647  			c.Logf("machine %q address updated: %+v", m.Id(), addrs)
   648  			break
   649  		}
   650  		c.Logf("waiting for machine %q address to be updated", m.Id())
   651  	}
   652  }
   653  
   654  func (s *MachineSuite) TestManageModelRunsPeergrouper(c *gc.C) {
   655  	started := newSignal()
   656  	s.AgentSuite.PatchValue(&peergrouperNew, func(st *state.State) (worker.Worker, error) {
   657  		c.Check(st, gc.NotNil)
   658  		started.trigger()
   659  		return newDummyWorker(), nil
   660  	})
   661  	m, _, _ := s.primeAgent(c, state.JobManageModel)
   662  	a := s.newAgent(c, m)
   663  	defer a.Stop()
   664  	go func() {
   665  		c.Check(a.Run(nil), jc.ErrorIsNil)
   666  	}()
   667  	started.assertTriggered(c, "peergrouperworker to start")
   668  }
   669  
   670  func (s *MachineSuite) TestManageModelRunsDbLogPrunerIfFeatureFlagEnabled(c *gc.C) {
   671  	m, _, _ := s.primeAgent(c, state.JobManageModel)
   672  	a := s.newAgent(c, m)
   673  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
   674  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
   675  
   676  	runner := s.singularRecord.nextRunner(c)
   677  	runner.waitForWorker(c, "dblogpruner")
   678  }
   679  
   680  func (s *MachineSuite) TestManageModelCallsUseMultipleCPUs(c *gc.C) {
   681  	// If it has been enabled, the JobManageModel agent should call utils.UseMultipleCPUs
   682  	usefulVersion := version.Binary{
   683  		Number: jujuversion.Current,
   684  		Arch:   arch.HostArch(),
   685  		Series: "quantal", // to match the charm created below
   686  	}
   687  	envtesting.AssertUploadFakeToolsVersions(
   688  		c, s.DefaultToolsStorage, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), usefulVersion)
   689  	m, _, _ := s.primeAgent(c, state.JobManageModel)
   690  	calledChan := make(chan struct{}, 1)
   691  	s.AgentSuite.PatchValue(&useMultipleCPUs, func() { calledChan <- struct{}{} })
   692  	// Now, start the agent, and observe that a JobManageModel agent
   693  	// calls UseMultipleCPUs
   694  	a := s.newAgent(c, m)
   695  	defer a.Stop()
   696  	go func() {
   697  		c.Check(a.Run(nil), jc.ErrorIsNil)
   698  	}()
   699  	// Wait for configuration to be finished
   700  	<-a.WorkersStarted()
   701  	s.assertChannelActive(c, calledChan, "UseMultipleCPUs() to be called")
   702  
   703  	c.Check(a.Stop(), jc.ErrorIsNil)
   704  	// However, an agent that just JobHostUnits doesn't call UseMultipleCPUs
   705  	m2, _, _ := s.primeAgent(c, state.JobHostUnits)
   706  	a2 := s.newAgent(c, m2)
   707  	defer a2.Stop()
   708  	go func() {
   709  		c.Check(a2.Run(nil), jc.ErrorIsNil)
   710  	}()
   711  	// Wait until all the workers have been started, and then kill everything
   712  	<-a2.workersStarted
   713  	c.Check(a2.Stop(), jc.ErrorIsNil)
   714  	s.assertChannelInactive(c, calledChan, "UseMultipleCPUs() was called")
   715  }
   716  
   717  func (s *MachineSuite) waitProvisioned(c *gc.C, unit *state.Unit) (*state.Machine, instance.Id) {
   718  	c.Logf("waiting for unit %q to be provisioned", unit)
   719  	machineId, err := unit.AssignedMachineId()
   720  	c.Assert(err, jc.ErrorIsNil)
   721  	m, err := s.State.Machine(machineId)
   722  	c.Assert(err, jc.ErrorIsNil)
   723  	w := m.Watch()
   724  	defer w.Stop()
   725  	timeout := time.After(coretesting.LongWait)
   726  	for {
   727  		select {
   728  		case <-timeout:
   729  			c.Fatalf("timed out waiting for provisioning")
   730  		case <-time.After(coretesting.ShortWait):
   731  			s.State.StartSync()
   732  		case _, ok := <-w.Changes():
   733  			c.Assert(ok, jc.IsTrue)
   734  			err := m.Refresh()
   735  			c.Assert(err, jc.ErrorIsNil)
   736  			if instId, err := m.InstanceId(); err == nil {
   737  				c.Logf("unit provisioned with instance %s", instId)
   738  				return m, instId
   739  			} else {
   740  				c.Check(err, jc.Satisfies, errors.IsNotProvisioned)
   741  			}
   742  		}
   743  	}
   744  }
   745  
   746  func (s *MachineSuite) testUpgradeRequest(c *gc.C, agent runner, tag string, currentTools *tools.Tools) {
   747  	newVers := version.Binary{
   748  		Number: jujuversion.Current,
   749  		Arch:   arch.HostArch(),
   750  		Series: series.HostSeries(),
   751  	}
   752  	newVers.Patch++
   753  	newTools := envtesting.AssertUploadFakeToolsVersions(
   754  		c, s.DefaultToolsStorage, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), newVers)[0]
   755  	err := s.State.SetModelAgentVersion(newVers.Number)
   756  	c.Assert(err, jc.ErrorIsNil)
   757  	err = runWithTimeout(agent)
   758  	envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{
   759  		AgentName: tag,
   760  		OldTools:  currentTools.Version,
   761  		NewTools:  newTools.Version,
   762  		DataDir:   s.DataDir(),
   763  	})
   764  }
   765  
   766  func (s *MachineSuite) TestUpgradeRequest(c *gc.C) {
   767  	m, _, currentTools := s.primeAgent(c, state.JobManageModel, state.JobHostUnits)
   768  	a := s.newAgent(c, m)
   769  	s.testUpgradeRequest(c, a, m.Tag().String(), currentTools)
   770  	c.Assert(a.isInitialUpgradeCheckPending(), jc.IsTrue)
   771  }
   772  
   773  func (s *MachineSuite) TestNoUpgradeRequired(c *gc.C) {
   774  	m, _, _ := s.primeAgent(c, state.JobManageModel, state.JobHostUnits)
   775  	a := s.newAgent(c, m)
   776  	done := make(chan error)
   777  	go func() { done <- a.Run(nil) }()
   778  	select {
   779  	case <-a.initialUpgradeCheckComplete.Unlocked():
   780  	case <-time.After(coretesting.LongWait):
   781  		c.Fatalf("timeout waiting for upgrade check")
   782  	}
   783  	defer a.Stop() // in case of failure
   784  	s.waitStopped(c, state.JobManageModel, a, done)
   785  	c.Assert(a.isInitialUpgradeCheckPending(), jc.IsFalse)
   786  }
   787  
   788  var fastDialOpts = api.DialOpts{
   789  	Timeout:    coretesting.LongWait,
   790  	RetryDelay: coretesting.ShortWait,
   791  }
   792  
   793  func (s *MachineSuite) waitStopped(c *gc.C, job state.MachineJob, a *MachineAgent, done chan error) {
   794  	err := a.Stop()
   795  	if job == state.JobManageModel {
   796  		// When shutting down, the API server can be shut down before
   797  		// the other workers that connect to it, so they get an error so
   798  		// they then die, causing Stop to return an error.  It's not
   799  		// easy to control the actual error that's received in this
   800  		// circumstance so we just log it rather than asserting that it
   801  		// is not nil.
   802  		if err != nil {
   803  			c.Logf("error shutting down state manager: %v", err)
   804  		}
   805  	} else {
   806  		c.Assert(err, jc.ErrorIsNil)
   807  	}
   808  
   809  	select {
   810  	case err := <-done:
   811  		c.Assert(err, jc.ErrorIsNil)
   812  	case <-time.After(coretesting.LongWait):
   813  		c.Fatalf("timed out waiting for agent to terminate")
   814  	}
   815  }
   816  
   817  func (s *MachineSuite) assertJobWithState(
   818  	c *gc.C,
   819  	job state.MachineJob,
   820  	test func(agent.Config, *state.State),
   821  ) {
   822  	paramsJob := job.ToParams()
   823  	if !paramsJob.NeedsState() {
   824  		c.Fatalf("%v does not use state", paramsJob)
   825  	}
   826  	s.assertAgentOpensState(c, &reportOpenedState, job, func(cfg agent.Config, st interface{}) {
   827  		test(cfg, st.(*state.State))
   828  	})
   829  }
   830  
   831  // assertAgentOpensState asserts that a machine agent started with the
   832  // given job will call the function pointed to by reportOpened. The
   833  // agent's configuration and the value passed to reportOpened are then
   834  // passed to the test function for further checking.
   835  func (s *MachineSuite) assertAgentOpensState(c *gc.C, reportOpened *func(io.Closer), job state.MachineJob, test func(agent.Config, interface{})) {
   836  	stm, conf, _ := s.primeAgent(c, job)
   837  	a := s.newAgent(c, stm)
   838  	defer a.Stop()
   839  	logger.Debugf("new agent %#v", a)
   840  
   841  	// All state jobs currently also run an APIWorker, so no
   842  	// need to check for that here, like in assertJobWithState.
   843  	agentAPI, done := s.waitForOpenState(c, reportOpened, a)
   844  	test(conf, agentAPI)
   845  	s.waitStopped(c, job, a, done)
   846  }
   847  
   848  func (s *MachineSuite) waitForOpenState(c *gc.C, reportOpened *func(io.Closer), a *MachineAgent) (interface{}, chan error) {
   849  	agentAPIs := make(chan io.Closer, 1)
   850  	s.AgentSuite.PatchValue(reportOpened, func(st io.Closer) {
   851  		select {
   852  		case agentAPIs <- st:
   853  		default:
   854  		}
   855  	})
   856  
   857  	done := make(chan error)
   858  	go func() {
   859  		done <- a.Run(nil)
   860  	}()
   861  
   862  	select {
   863  	case agentAPI := <-agentAPIs:
   864  		c.Assert(agentAPI, gc.NotNil)
   865  		return agentAPI, done
   866  	case <-time.After(coretesting.LongWait):
   867  		c.Fatalf("API not opened")
   868  	}
   869  	panic("can't happen")
   870  }
   871  
   872  func (s *MachineSuite) TestManageModelServesAPI(c *gc.C) {
   873  	s.assertJobWithState(c, state.JobManageModel, func(conf agent.Config, agentState *state.State) {
   874  		apiInfo, ok := conf.APIInfo()
   875  		c.Assert(ok, jc.IsTrue)
   876  		st, err := api.Open(apiInfo, fastDialOpts)
   877  		c.Assert(err, jc.ErrorIsNil)
   878  		defer st.Close()
   879  		m, err := apimachiner.NewState(st).Machine(conf.Tag().(names.MachineTag))
   880  		c.Assert(err, jc.ErrorIsNil)
   881  		c.Assert(m.Life(), gc.Equals, params.Alive)
   882  	})
   883  }
   884  
   885  func (s *MachineSuite) assertAgentSetsToolsVersion(c *gc.C, job state.MachineJob) {
   886  	vers := version.Binary{
   887  		Number: jujuversion.Current,
   888  		Arch:   arch.HostArch(),
   889  		Series: series.HostSeries(),
   890  	}
   891  	vers.Minor++
   892  	m, _, _ := s.primeAgentVersion(c, vers, job)
   893  	a := s.newAgent(c, m)
   894  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
   895  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
   896  
   897  	timeout := time.After(coretesting.LongWait)
   898  	for done := false; !done; {
   899  		select {
   900  		case <-timeout:
   901  			c.Fatalf("timeout while waiting for agent version to be set")
   902  		case <-time.After(coretesting.ShortWait):
   903  			c.Log("Refreshing")
   904  			err := m.Refresh()
   905  			c.Assert(err, jc.ErrorIsNil)
   906  			c.Log("Fetching agent tools")
   907  			agentTools, err := m.AgentTools()
   908  			c.Assert(err, jc.ErrorIsNil)
   909  			c.Logf("(%v vs. %v)", agentTools.Version, jujuversion.Current)
   910  			if agentTools.Version.Minor != jujuversion.Current.Minor {
   911  				continue
   912  			}
   913  			c.Assert(agentTools.Version.Number, gc.DeepEquals, jujuversion.Current)
   914  			done = true
   915  		}
   916  	}
   917  }
   918  
   919  func (s *MachineSuite) TestAgentSetsToolsVersionManageModel(c *gc.C) {
   920  	s.assertAgentSetsToolsVersion(c, state.JobManageModel)
   921  }
   922  
   923  func (s *MachineSuite) TestAgentSetsToolsVersionHostUnits(c *gc.C) {
   924  	s.assertAgentSetsToolsVersion(c, state.JobHostUnits)
   925  }
   926  
   927  func (s *MachineSuite) TestManageModelRunsCleaner(c *gc.C) {
   928  	s.assertJobWithState(c, state.JobManageModel, func(conf agent.Config, agentState *state.State) {
   929  		// Create a service and unit, and destroy the service.
   930  		service := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   931  		unit, err := service.AddUnit()
   932  		c.Assert(err, jc.ErrorIsNil)
   933  		err = service.Destroy()
   934  		c.Assert(err, jc.ErrorIsNil)
   935  
   936  		// Check the unit was not yet removed.
   937  		err = unit.Refresh()
   938  		c.Assert(err, jc.ErrorIsNil)
   939  		w := unit.Watch()
   940  		defer w.Stop()
   941  
   942  		// Trigger a sync on the state used by the agent, and wait
   943  		// for the unit to be removed.
   944  		agentState.StartSync()
   945  		timeout := time.After(coretesting.LongWait)
   946  		for done := false; !done; {
   947  			select {
   948  			case <-timeout:
   949  				c.Fatalf("unit not cleaned up")
   950  			case <-time.After(coretesting.ShortWait):
   951  				s.State.StartSync()
   952  			case <-w.Changes():
   953  				err := unit.Refresh()
   954  				if errors.IsNotFound(err) {
   955  					done = true
   956  				} else {
   957  					c.Assert(err, jc.ErrorIsNil)
   958  				}
   959  			}
   960  		}
   961  	})
   962  }
   963  
   964  func (s *MachineSuite) TestJobManageModelRunsMinUnitsWorker(c *gc.C) {
   965  	s.assertJobWithState(c, state.JobManageModel, func(_ agent.Config, agentState *state.State) {
   966  		// Ensure that the MinUnits worker is alive by doing a simple check
   967  		// that it responds to state changes: add a service, set its minimum
   968  		// number of units to one, wait for the worker to add the missing unit.
   969  		service := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   970  		err := service.SetMinUnits(1)
   971  		c.Assert(err, jc.ErrorIsNil)
   972  		w := service.Watch()
   973  		defer w.Stop()
   974  
   975  		// Trigger a sync on the state used by the agent, and wait for the unit
   976  		// to be created.
   977  		agentState.StartSync()
   978  		timeout := time.After(coretesting.LongWait)
   979  		for {
   980  			select {
   981  			case <-timeout:
   982  				c.Fatalf("unit not created")
   983  			case <-time.After(coretesting.ShortWait):
   984  				s.State.StartSync()
   985  			case <-w.Changes():
   986  				units, err := service.AllUnits()
   987  				c.Assert(err, jc.ErrorIsNil)
   988  				if len(units) == 1 {
   989  					return
   990  				}
   991  			}
   992  		}
   993  	})
   994  }
   995  
   996  func (s *MachineSuite) TestMachineAgentRunsAuthorisedKeysWorker(c *gc.C) {
   997  	//TODO(bogdanteleaga): Fix once we get authentication worker up on windows
   998  	if runtime.GOOS == "windows" {
   999  		c.Skip("bug 1403084: authentication worker not yet implemented on windows")
  1000  	}
  1001  	// Start the machine agent.
  1002  	m, _, _ := s.primeAgent(c, state.JobHostUnits)
  1003  	a := s.newAgent(c, m)
  1004  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1005  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1006  
  1007  	// Update the keys in the environment.
  1008  	sshKey := sshtesting.ValidKeyOne.Key + " user@host"
  1009  	err := s.BackingState.UpdateModelConfig(map[string]interface{}{"authorized-keys": sshKey}, nil, nil)
  1010  	c.Assert(err, jc.ErrorIsNil)
  1011  
  1012  	// Wait for ssh keys file to be updated.
  1013  	s.State.StartSync()
  1014  	timeout := time.After(coretesting.LongWait)
  1015  	sshKeyWithCommentPrefix := sshtesting.ValidKeyOne.Key + " Juju:user@host"
  1016  	for {
  1017  		select {
  1018  		case <-timeout:
  1019  			c.Fatalf("timeout while waiting for authorised ssh keys to change")
  1020  		case <-time.After(coretesting.ShortWait):
  1021  			s.State.StartSync()
  1022  			keys, err := ssh.ListKeys(authenticationworker.SSHUser, ssh.FullKeys)
  1023  			c.Assert(err, jc.ErrorIsNil)
  1024  			keysStr := strings.Join(keys, "\n")
  1025  			if sshKeyWithCommentPrefix != keysStr {
  1026  				continue
  1027  			}
  1028  			return
  1029  		}
  1030  	}
  1031  }
  1032  
  1033  // opRecvTimeout waits for any of the given kinds of operation to
  1034  // be received from ops, and times out if not.
  1035  func opRecvTimeout(c *gc.C, st *state.State, opc <-chan dummy.Operation, kinds ...dummy.Operation) dummy.Operation {
  1036  	st.StartSync()
  1037  	timeout := time.After(coretesting.LongWait)
  1038  	for {
  1039  		select {
  1040  		case op := <-opc:
  1041  			for _, k := range kinds {
  1042  				if reflect.TypeOf(op) == reflect.TypeOf(k) {
  1043  					return op
  1044  				}
  1045  			}
  1046  			c.Logf("discarding unknown event %#v", op)
  1047  		case <-time.After(coretesting.ShortWait):
  1048  			st.StartSync()
  1049  		case <-timeout:
  1050  			c.Fatalf("time out wating for operation")
  1051  		}
  1052  	}
  1053  }
  1054  
  1055  func (s *MachineSuite) TestMachineAgentSymlinks(c *gc.C) {
  1056  	stm, _, _ := s.primeAgent(c, state.JobManageModel)
  1057  	a := s.newAgent(c, stm)
  1058  	defer a.Stop()
  1059  	_, done := s.waitForOpenState(c, &reportOpenedState, a)
  1060  
  1061  	// Symlinks should have been created
  1062  	for _, link := range []string{jujuRun, jujuDumpLogs} {
  1063  		_, err := os.Stat(utils.EnsureBaseDir(a.rootDir, link))
  1064  		c.Assert(err, jc.ErrorIsNil, gc.Commentf(link))
  1065  	}
  1066  
  1067  	s.waitStopped(c, state.JobManageModel, a, done)
  1068  }
  1069  
  1070  func (s *MachineSuite) TestMachineAgentSymlinkJujuRunExists(c *gc.C) {
  1071  	if runtime.GOOS == "windows" {
  1072  		// Cannot make symlink to nonexistent file on windows or
  1073  		// create a file point a symlink to it then remove it
  1074  		c.Skip("Cannot test this on windows")
  1075  	}
  1076  
  1077  	stm, _, _ := s.primeAgent(c, state.JobManageModel)
  1078  	a := s.newAgent(c, stm)
  1079  	defer a.Stop()
  1080  
  1081  	// Pre-create the symlinks, but pointing to the incorrect location.
  1082  	links := []string{jujuRun, jujuDumpLogs}
  1083  	a.rootDir = c.MkDir()
  1084  	for _, link := range links {
  1085  		fullLink := utils.EnsureBaseDir(a.rootDir, link)
  1086  		c.Assert(os.MkdirAll(filepath.Dir(fullLink), os.FileMode(0755)), jc.ErrorIsNil)
  1087  		c.Assert(symlink.New("/nowhere/special", fullLink), jc.ErrorIsNil, gc.Commentf(link))
  1088  	}
  1089  
  1090  	// Start the agent and wait for it be running.
  1091  	_, done := s.waitForOpenState(c, &reportOpenedState, a)
  1092  
  1093  	// juju-run symlink should have been recreated.
  1094  	for _, link := range links {
  1095  		fullLink := utils.EnsureBaseDir(a.rootDir, link)
  1096  		linkTarget, err := symlink.Read(fullLink)
  1097  		c.Assert(err, jc.ErrorIsNil)
  1098  		c.Assert(linkTarget, gc.Not(gc.Equals), "/nowhere/special", gc.Commentf(link))
  1099  	}
  1100  
  1101  	s.waitStopped(c, state.JobManageModel, a, done)
  1102  }
  1103  
  1104  func (s *MachineSuite) TestMachineAgentUninstall(c *gc.C) {
  1105  	m, ac, _ := s.primeAgent(c, state.JobHostUnits)
  1106  	err := m.EnsureDead()
  1107  	c.Assert(err, jc.ErrorIsNil)
  1108  	a := s.newAgent(c, m)
  1109  	err = runWithTimeout(a)
  1110  	c.Assert(err, jc.ErrorIsNil)
  1111  
  1112  	// juju-run and juju-dumplogs symlinks should have been removed on
  1113  	// termination.
  1114  	for _, link := range []string{jujuRun, jujuDumpLogs} {
  1115  		_, err = os.Stat(utils.EnsureBaseDir(a.rootDir, link))
  1116  		c.Assert(err, jc.Satisfies, os.IsNotExist)
  1117  	}
  1118  
  1119  	// data-dir should have been removed on termination
  1120  	_, err = os.Stat(ac.DataDir())
  1121  	c.Assert(err, jc.Satisfies, os.IsNotExist)
  1122  }
  1123  
  1124  func (s *MachineSuite) TestMachineAgentRunsAPIAddressUpdaterWorker(c *gc.C) {
  1125  	// Start the machine agent.
  1126  	m, _, _ := s.primeAgent(c, state.JobHostUnits)
  1127  	a := s.newAgent(c, m)
  1128  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1129  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1130  
  1131  	// Update the API addresses.
  1132  	updatedServers := [][]network.HostPort{
  1133  		network.NewHostPorts(1234, "localhost"),
  1134  	}
  1135  	err := s.BackingState.SetAPIHostPorts(updatedServers)
  1136  	c.Assert(err, jc.ErrorIsNil)
  1137  
  1138  	// Wait for config to be updated.
  1139  	for attempt := coretesting.LongAttempt.Start(); attempt.Next(); {
  1140  		s.BackingState.StartSync()
  1141  		if !attempt.HasNext() {
  1142  			break
  1143  		}
  1144  		addrs, err := a.CurrentConfig().APIAddresses()
  1145  		c.Assert(err, jc.ErrorIsNil)
  1146  		if reflect.DeepEqual(addrs, []string{"localhost:1234"}) {
  1147  			return
  1148  		}
  1149  	}
  1150  	c.Fatalf("timeout while waiting for agent config to change")
  1151  }
  1152  
  1153  func (s *MachineSuite) TestMachineAgentRunsDiskManagerWorker(c *gc.C) {
  1154  	// Patch out the worker func before starting the agent.
  1155  	started := newSignal()
  1156  	newWorker := func(diskmanager.ListBlockDevicesFunc, diskmanager.BlockDeviceSetter) worker.Worker {
  1157  		started.trigger()
  1158  		return worker.NewNoOpWorker()
  1159  	}
  1160  	s.PatchValue(&diskmanager.NewWorker, newWorker)
  1161  
  1162  	// Start the machine agent.
  1163  	m, _, _ := s.primeAgent(c, state.JobHostUnits)
  1164  	a := s.newAgent(c, m)
  1165  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1166  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1167  	started.assertTriggered(c, "diskmanager worker to start")
  1168  }
  1169  
  1170  func (s *MachineSuite) TestMongoUpgradeWorker(c *gc.C) {
  1171  	// Patch out the worker func before starting the agent.
  1172  	started := make(chan struct{})
  1173  	newWorker := func(*state.State, string, mongoupgrader.StopMongo) (worker.Worker, error) {
  1174  		close(started)
  1175  		return worker.NewNoOpWorker(), nil
  1176  	}
  1177  	s.PatchValue(&newUpgradeMongoWorker, newWorker)
  1178  
  1179  	// Start the machine agent.
  1180  	m, _, _ := s.primeAgent(c, state.JobManageModel)
  1181  	a := s.newAgent(c, m)
  1182  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1183  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1184  
  1185  	// Wait for worker to be started.
  1186  	s.State.StartSync()
  1187  	select {
  1188  	case <-started:
  1189  	case <-time.After(coretesting.LongWait):
  1190  		c.Fatalf("timeout while waiting for mongo upgrader worker to start")
  1191  	}
  1192  }
  1193  
  1194  func (s *MachineSuite) TestDiskManagerWorkerUpdatesState(c *gc.C) {
  1195  	expected := []storage.BlockDevice{{DeviceName: "whatever"}}
  1196  	s.PatchValue(&diskmanager.DefaultListBlockDevices, func() ([]storage.BlockDevice, error) {
  1197  		return expected, nil
  1198  	})
  1199  
  1200  	// Start the machine agent.
  1201  	m, _, _ := s.primeAgent(c, state.JobHostUnits)
  1202  	a := s.newAgent(c, m)
  1203  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1204  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1205  
  1206  	// Wait for state to be updated.
  1207  	s.BackingState.StartSync()
  1208  	for attempt := coretesting.LongAttempt.Start(); attempt.Next(); {
  1209  		devices, err := s.BackingState.BlockDevices(m.MachineTag())
  1210  		c.Assert(err, jc.ErrorIsNil)
  1211  		if len(devices) > 0 {
  1212  			c.Assert(devices, gc.HasLen, 1)
  1213  			c.Assert(devices[0].DeviceName, gc.Equals, expected[0].DeviceName)
  1214  			return
  1215  		}
  1216  	}
  1217  	c.Fatalf("timeout while waiting for block devices to be recorded")
  1218  }
  1219  
  1220  func (s *MachineSuite) TestMachineAgentDoesNotRunMetadataWorkerForHostUnits(c *gc.C) {
  1221  	s.checkMetadataWorkerNotRun(c, state.JobHostUnits, "can host units")
  1222  }
  1223  
  1224  func (s *MachineSuite) TestMachineAgentDoesNotRunMetadataWorkerForManageNetworking(c *gc.C) {
  1225  	s.checkMetadataWorkerNotRun(c, state.JobManageNetworking, "can manage networking")
  1226  }
  1227  
  1228  func (s *MachineSuite) TestMachineAgentDoesNotRunMetadataWorkerForNonSimpleStreamDependentProviders(c *gc.C) {
  1229  	s.checkMetadataWorkerNotRun(c, state.JobManageModel, "has provider which doesn't depend on simple streams")
  1230  }
  1231  
  1232  func (s *MachineSuite) checkMetadataWorkerNotRun(c *gc.C, job state.MachineJob, suffix string) {
  1233  	// Patch out the worker func before starting the agent.
  1234  	started := newSignal()
  1235  	newWorker := func(cl *imagemetadata.Client) worker.Worker {
  1236  		started.trigger()
  1237  		return worker.NewNoOpWorker()
  1238  	}
  1239  	s.PatchValue(&newMetadataUpdater, newWorker)
  1240  
  1241  	// Start the machine agent.
  1242  	m, _, _ := s.primeAgent(c, job)
  1243  	a := s.newAgent(c, m)
  1244  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1245  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1246  	started.assertNotTriggered(c, startWorkerWait, "metadata update worker started")
  1247  }
  1248  
  1249  func (s *MachineSuite) TestMachineAgentRunsMachineStorageWorker(c *gc.C) {
  1250  	m, _, _ := s.primeAgent(c, state.JobHostUnits)
  1251  
  1252  	started := newSignal()
  1253  	newWorker := func(config storageprovisioner.Config) (worker.Worker, error) {
  1254  		c.Check(config.Scope, gc.Equals, m.Tag())
  1255  		c.Check(config.Validate(), jc.ErrorIsNil)
  1256  		started.trigger()
  1257  		return worker.NewNoOpWorker(), nil
  1258  	}
  1259  	s.PatchValue(&storageprovisioner.NewStorageProvisioner, newWorker)
  1260  
  1261  	// Start the machine agent.
  1262  	a := s.newAgent(c, m)
  1263  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1264  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1265  	started.assertTriggered(c, "storage worker to start")
  1266  }
  1267  
  1268  func (s *MachineSuite) TestMachineAgentRunsCertificateUpdateWorkerForController(c *gc.C) {
  1269  	started := newSignal()
  1270  	newUpdater := func(certupdater.AddressWatcher, certupdater.StateServingInfoGetter, certupdater.ModelConfigGetter,
  1271  		certupdater.APIHostPortsGetter, certupdater.StateServingInfoSetter,
  1272  	) worker.Worker {
  1273  		started.trigger()
  1274  		return worker.NewNoOpWorker()
  1275  	}
  1276  	s.PatchValue(&newCertificateUpdater, newUpdater)
  1277  
  1278  	// Start the machine agent.
  1279  	m, _, _ := s.primeAgent(c, state.JobManageModel)
  1280  	a := s.newAgent(c, m)
  1281  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1282  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1283  	started.assertTriggered(c, "certificate to be updated")
  1284  }
  1285  
  1286  func (s *MachineSuite) TestMachineAgentDoesNotRunsCertificateUpdateWorkerForNonController(c *gc.C) {
  1287  	started := newSignal()
  1288  	newUpdater := func(certupdater.AddressWatcher, certupdater.StateServingInfoGetter, certupdater.ModelConfigGetter,
  1289  		certupdater.APIHostPortsGetter, certupdater.StateServingInfoSetter,
  1290  	) worker.Worker {
  1291  		started.trigger()
  1292  		return worker.NewNoOpWorker()
  1293  	}
  1294  	s.PatchValue(&newCertificateUpdater, newUpdater)
  1295  
  1296  	// Start the machine agent.
  1297  	m, _, _ := s.primeAgent(c, state.JobHostUnits)
  1298  	a := s.newAgent(c, m)
  1299  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1300  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1301  	started.assertNotTriggered(c, startWorkerWait, "certificate was updated")
  1302  }
  1303  
  1304  func (s *MachineSuite) TestCertificateUpdateWorkerUpdatesCertificate(c *gc.C) {
  1305  	// Set up the machine agent.
  1306  	m, _, _ := s.primeAgent(c, state.JobManageModel)
  1307  	a := s.newAgent(c, m)
  1308  	a.ReadConfig(names.NewMachineTag(m.Id()).String())
  1309  
  1310  	// Set up check that certificate has been updated.
  1311  	updated := make(chan struct{})
  1312  	go func() {
  1313  		for {
  1314  			stateInfo, _ := a.CurrentConfig().StateServingInfo()
  1315  			srvCert, err := cert.ParseCert(stateInfo.Cert)
  1316  			c.Assert(err, jc.ErrorIsNil)
  1317  			sanIPs := make([]string, len(srvCert.IPAddresses))
  1318  			for i, ip := range srvCert.IPAddresses {
  1319  				sanIPs[i] = ip.String()
  1320  			}
  1321  			if len(sanIPs) == 1 && sanIPs[0] == "0.1.2.3" {
  1322  				close(updated)
  1323  				break
  1324  			}
  1325  			time.Sleep(10 * time.Millisecond)
  1326  		}
  1327  	}()
  1328  
  1329  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1330  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1331  	s.assertChannelActive(c, updated, "certificate to be updated")
  1332  }
  1333  
  1334  func (s *MachineSuite) TestCertificateDNSUpdated(c *gc.C) {
  1335  	// Disable the certificate work so it doesn't update the certificate.
  1336  	newUpdater := func(certupdater.AddressWatcher, certupdater.StateServingInfoGetter, certupdater.ModelConfigGetter,
  1337  		certupdater.APIHostPortsGetter, certupdater.StateServingInfoSetter,
  1338  	) worker.Worker {
  1339  		return worker.NewNoOpWorker()
  1340  	}
  1341  	s.PatchValue(&newCertificateUpdater, newUpdater)
  1342  
  1343  	// Set up the machine agent.
  1344  	m, _, _ := s.primeAgent(c, state.JobManageModel)
  1345  	a := s.newAgent(c, m)
  1346  
  1347  	// Set up check that certificate has been updated when the agent starts.
  1348  	updated := make(chan struct{})
  1349  	expectedDnsNames := set.NewStrings("local", "juju-apiserver", "juju-mongodb")
  1350  	go func() {
  1351  		for {
  1352  			stateInfo, _ := a.CurrentConfig().StateServingInfo()
  1353  			srvCert, err := cert.ParseCert(stateInfo.Cert)
  1354  			c.Assert(err, jc.ErrorIsNil)
  1355  			certDnsNames := set.NewStrings(srvCert.DNSNames...)
  1356  			if !expectedDnsNames.Difference(certDnsNames).IsEmpty() {
  1357  				continue
  1358  			}
  1359  			pemContent, err := ioutil.ReadFile(filepath.Join(s.DataDir(), "server.pem"))
  1360  			c.Assert(err, jc.ErrorIsNil)
  1361  			if string(pemContent) == stateInfo.Cert+"\n"+stateInfo.PrivateKey {
  1362  				close(updated)
  1363  				break
  1364  			}
  1365  			time.Sleep(10 * time.Millisecond)
  1366  		}
  1367  	}()
  1368  
  1369  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1370  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1371  	s.assertChannelActive(c, updated, "certificate to be updated")
  1372  }
  1373  
  1374  func (s *MachineSuite) setupIgnoreAddresses(c *gc.C, expectedIgnoreValue bool) chan bool {
  1375  	ignoreAddressCh := make(chan bool, 1)
  1376  	s.AgentSuite.PatchValue(&machiner.NewMachiner, func(cfg machiner.Config) (worker.Worker, error) {
  1377  		select {
  1378  		case ignoreAddressCh <- cfg.ClearMachineAddressesOnStart:
  1379  		default:
  1380  		}
  1381  
  1382  		// The test just cares that NewMachiner is called with the correct
  1383  		// value, nothing else is done with the worker.
  1384  		return newDummyWorker(), nil
  1385  	})
  1386  
  1387  	attrs := coretesting.Attrs{"ignore-machine-addresses": expectedIgnoreValue}
  1388  	err := s.BackingState.UpdateModelConfig(attrs, nil, nil)
  1389  	c.Assert(err, jc.ErrorIsNil)
  1390  	return ignoreAddressCh
  1391  }
  1392  
  1393  func (s *MachineSuite) TestMachineAgentIgnoreAddresses(c *gc.C) {
  1394  	for _, expectedIgnoreValue := range []bool{true, false} {
  1395  		ignoreAddressCh := s.setupIgnoreAddresses(c, expectedIgnoreValue)
  1396  
  1397  		m, _, _ := s.primeAgent(c, state.JobHostUnits)
  1398  		a := s.newAgent(c, m)
  1399  		defer a.Stop()
  1400  		doneCh := make(chan error)
  1401  		go func() {
  1402  			doneCh <- a.Run(nil)
  1403  		}()
  1404  
  1405  		select {
  1406  		case ignoreMachineAddresses := <-ignoreAddressCh:
  1407  			if ignoreMachineAddresses != expectedIgnoreValue {
  1408  				c.Fatalf("expected ignore-machine-addresses = %v, got = %v", expectedIgnoreValue, ignoreMachineAddresses)
  1409  			}
  1410  		case <-time.After(coretesting.LongWait):
  1411  			c.Fatalf("timed out waiting for the machiner to start")
  1412  		}
  1413  		s.waitStopped(c, state.JobHostUnits, a, doneCh)
  1414  	}
  1415  }
  1416  
  1417  func (s *MachineSuite) TestMachineAgentIgnoreAddressesContainer(c *gc.C) {
  1418  	ignoreAddressCh := s.setupIgnoreAddresses(c, true)
  1419  
  1420  	parent, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1421  	c.Assert(err, jc.ErrorIsNil)
  1422  	m, err := s.State.AddMachineInsideMachine(
  1423  		state.MachineTemplate{
  1424  			Series: "trusty",
  1425  			Jobs:   []state.MachineJob{state.JobHostUnits},
  1426  		},
  1427  		parent.Id(),
  1428  		instance.LXC,
  1429  	)
  1430  	c.Assert(err, jc.ErrorIsNil)
  1431  
  1432  	vers := version.Binary{
  1433  		Number: jujuversion.Current,
  1434  		Arch:   arch.HostArch(),
  1435  		Series: series.HostSeries(),
  1436  	}
  1437  	s.primeAgentWithMachine(c, m, vers)
  1438  	a := s.newAgent(c, m)
  1439  	defer a.Stop()
  1440  	doneCh := make(chan error)
  1441  	go func() {
  1442  		doneCh <- a.Run(nil)
  1443  	}()
  1444  
  1445  	select {
  1446  	case ignoreMachineAddresses := <-ignoreAddressCh:
  1447  		if ignoreMachineAddresses {
  1448  			c.Fatalf("expected ignore-machine-addresses = false, got = true")
  1449  		}
  1450  	case <-time.After(coretesting.LongWait):
  1451  		c.Fatalf("timed out waiting for the machiner to start")
  1452  	}
  1453  	s.waitStopped(c, state.JobHostUnits, a, doneCh)
  1454  }
  1455  
  1456  func (s *MachineSuite) TestMachineAgentSetsPrepareRestore(c *gc.C) {
  1457  	// Start the machine agent.
  1458  	m, _, _ := s.primeAgent(c, 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  	c.Check(a.IsRestorePreparing(), jc.IsFalse)
  1463  	c.Check(a.IsRestoreRunning(), jc.IsFalse)
  1464  	err := a.PrepareRestore()
  1465  	c.Assert(err, jc.ErrorIsNil)
  1466  	c.Assert(a.IsRestorePreparing(), jc.IsTrue)
  1467  	c.Assert(a.IsRestoreRunning(), jc.IsFalse)
  1468  	err = a.PrepareRestore()
  1469  	c.Assert(err, gc.ErrorMatches, "already in restore mode")
  1470  }
  1471  
  1472  func (s *MachineSuite) TestMachineAgentSetsRestoreInProgress(c *gc.C) {
  1473  	// Start the machine agent.
  1474  	m, _, _ := s.primeAgent(c, state.JobHostUnits)
  1475  	a := s.newAgent(c, m)
  1476  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1477  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1478  	c.Check(a.IsRestorePreparing(), jc.IsFalse)
  1479  	c.Check(a.IsRestoreRunning(), jc.IsFalse)
  1480  	err := a.PrepareRestore()
  1481  	c.Assert(err, jc.ErrorIsNil)
  1482  	c.Assert(a.IsRestorePreparing(), jc.IsTrue)
  1483  	err = a.BeginRestore()
  1484  	c.Assert(err, jc.ErrorIsNil)
  1485  	c.Assert(a.IsRestoreRunning(), jc.IsTrue)
  1486  	err = a.BeginRestore()
  1487  	c.Assert(err, gc.ErrorMatches, "already restoring")
  1488  }
  1489  
  1490  func (s *MachineSuite) TestMachineAgentRestoreRequiresPrepare(c *gc.C) {
  1491  	// Start the machine agent.
  1492  	m, _, _ := s.primeAgent(c, state.JobHostUnits)
  1493  	a := s.newAgent(c, m)
  1494  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
  1495  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1496  	c.Check(a.IsRestorePreparing(), jc.IsFalse)
  1497  	c.Check(a.IsRestoreRunning(), jc.IsFalse)
  1498  	err := a.BeginRestore()
  1499  	c.Assert(err, gc.ErrorMatches, "not in restore mode, cannot begin restoration")
  1500  	c.Assert(a.IsRestoreRunning(), jc.IsFalse)
  1501  }
  1502  
  1503  func (s *MachineSuite) TestControllerModelWorkers(c *gc.C) {
  1504  	tracker := newModelTracker(c)
  1505  	check := modelMatchFunc(c, tracker, append(
  1506  		alwaysModelWorkers, aliveModelWorkers...,
  1507  	))
  1508  	s.PatchValue(&modelManifolds, tracker.Manifolds)
  1509  
  1510  	uuid := s.BackingState.ModelUUID()
  1511  	timeout := time.After(coretesting.LongWait)
  1512  
  1513  	s.assertJobWithState(c, state.JobManageModel, func(_ agent.Config, _ *state.State) {
  1514  		for {
  1515  			if check(uuid) {
  1516  				break
  1517  			}
  1518  			select {
  1519  			case <-time.After(coretesting.ShortWait):
  1520  				s.BackingState.StartSync()
  1521  			case <-timeout:
  1522  				c.Fatalf("timed out waiting for workers")
  1523  			}
  1524  		}
  1525  	})
  1526  }
  1527  
  1528  func (s *MachineSuite) TestAddressAllocationModelWorkers(c *gc.C) {
  1529  	s.SetFeatureFlags(feature.AddressAllocation)
  1530  
  1531  	tracker := newModelTracker(c)
  1532  	almostAllWorkers := append(alwaysModelWorkers, aliveModelWorkers...)
  1533  	check := modelMatchFunc(c, tracker, append(
  1534  		almostAllWorkers, "address-cleaner",
  1535  	))
  1536  	s.PatchValue(&modelManifolds, tracker.Manifolds)
  1537  
  1538  	uuid := s.BackingState.ModelUUID()
  1539  	timeout := time.After(coretesting.LongWait)
  1540  
  1541  	s.assertJobWithState(c, state.JobManageModel, func(_ agent.Config, _ *state.State) {
  1542  		for {
  1543  			if check(uuid) {
  1544  				break
  1545  			}
  1546  			select {
  1547  			case <-time.After(coretesting.ShortWait):
  1548  				s.BackingState.StartSync()
  1549  			case <-timeout:
  1550  				c.Fatalf("timed out waiting for workers")
  1551  			}
  1552  		}
  1553  	})
  1554  }
  1555  
  1556  func (s *MachineSuite) TestHostedModelWorkers(c *gc.C) {
  1557  	tracker := newModelTracker(c)
  1558  	check := modelMatchFunc(c, tracker, append(
  1559  		alwaysModelWorkers, aliveModelWorkers...,
  1560  	))
  1561  	s.PatchValue(&modelManifolds, tracker.Manifolds)
  1562  
  1563  	st, closer := s.setUpNewModel(c)
  1564  	defer closer()
  1565  	uuid := st.ModelUUID()
  1566  	timeout := time.After(ReallyLongWait)
  1567  
  1568  	s.assertJobWithState(c, state.JobManageModel, func(_ agent.Config, _ *state.State) {
  1569  		for {
  1570  			if check(uuid) {
  1571  				break
  1572  			}
  1573  			select {
  1574  			case <-time.After(coretesting.ShortWait):
  1575  				s.BackingState.StartSync()
  1576  			case <-timeout:
  1577  				c.Fatalf("timed out waiting for workers")
  1578  			}
  1579  		}
  1580  	})
  1581  }
  1582  
  1583  func (s *MachineSuite) TestDyingModelCleanedUp(c *gc.C) {
  1584  	tracker := newModelTracker(c)
  1585  	check := modelMatchFunc(c, tracker, append(
  1586  		alwaysModelWorkers, deadModelWorkers...,
  1587  	))
  1588  	s.PatchValue(&modelManifolds, tracker.Manifolds)
  1589  
  1590  	st, closer := s.setUpNewModel(c)
  1591  	defer closer()
  1592  	uuid := st.ModelUUID()
  1593  	timeout := time.After(ReallyLongWait)
  1594  
  1595  	s.assertJobWithState(c, state.JobManageModel, func(_ agent.Config, _ *state.State) {
  1596  		model, err := st.Model()
  1597  		c.Assert(err, jc.ErrorIsNil)
  1598  		err = model.Destroy()
  1599  		c.Assert(err, jc.ErrorIsNil)
  1600  
  1601  		// Wait for the running workers to imply that we've
  1602  		// passed beyond Dying...
  1603  		for {
  1604  			if check(uuid) {
  1605  				break
  1606  			}
  1607  			select {
  1608  			case <-time.After(coretesting.ShortWait):
  1609  				s.BackingState.StartSync()
  1610  			case <-timeout:
  1611  				c.Fatalf("timed out waiting for workers")
  1612  			}
  1613  		}
  1614  
  1615  		// ...and verify that's reflected in the database.
  1616  		err = model.Refresh()
  1617  		c.Check(err, jc.ErrorIsNil)
  1618  		c.Check(model.Life(), gc.Equals, state.Dead)
  1619  	})
  1620  }
  1621  
  1622  func (s *MachineSuite) TestModelWorkersRespectSingularResponsibilityFlag(c *gc.C) {
  1623  
  1624  	// Grab responsibility for the model on behalf of another machine.
  1625  	claimer := s.BackingState.SingularClaimer()
  1626  	uuid := s.BackingState.ModelUUID()
  1627  	err := claimer.Claim(uuid, "machine-999-lxc-99", time.Hour)
  1628  	c.Assert(err, jc.ErrorIsNil)
  1629  
  1630  	// Then run a normal model-tracking test, just checking for
  1631  	// a different set of workers.
  1632  	tracker := newModelTracker(c)
  1633  	check := modelMatchFunc(c, tracker, alwaysModelWorkers)
  1634  	s.PatchValue(&modelManifolds, tracker.Manifolds)
  1635  
  1636  	timeout := time.After(coretesting.LongWait)
  1637  	s.assertJobWithState(c, state.JobManageModel, func(_ agent.Config, _ *state.State) {
  1638  		for {
  1639  			if check(uuid) {
  1640  				break
  1641  			}
  1642  			select {
  1643  			case <-time.After(coretesting.ShortWait):
  1644  				s.BackingState.StartSync()
  1645  			case <-timeout:
  1646  				c.Fatalf("timed out waiting for workers")
  1647  			}
  1648  		}
  1649  	})
  1650  }
  1651  
  1652  func (s *MachineSuite) setUpNewModel(c *gc.C) (newSt *state.State, closer func()) {
  1653  	// Create a new environment, tests can now watch if workers start for it.
  1654  	newSt = s.Factory.MakeModel(c, nil)
  1655  	return newSt, func() {
  1656  		err := newSt.Close()
  1657  		c.Check(err, jc.ErrorIsNil)
  1658  	}
  1659  }
  1660  
  1661  func (s *MachineSuite) TestReplicasetInitForNewController(c *gc.C) {
  1662  	if runtime.GOOS == "windows" {
  1663  		c.Skip("controllers on windows aren't supported")
  1664  	}
  1665  
  1666  	s.fakeEnsureMongo.ServiceInstalled = false
  1667  
  1668  	m, _, _ := s.primeAgent(c, state.JobManageModel)
  1669  	a := s.newAgent(c, m)
  1670  	agentConfig := a.CurrentConfig()
  1671  
  1672  	err := a.ensureMongoServer(agentConfig)
  1673  	c.Assert(err, jc.ErrorIsNil)
  1674  
  1675  	c.Assert(s.fakeEnsureMongo.EnsureCount, gc.Equals, 1)
  1676  	c.Assert(s.fakeEnsureMongo.InitiateCount, gc.Equals, 0)
  1677  }
  1678  
  1679  // MachineWithCharmsSuite provides infrastructure for tests which need to
  1680  // work with charms.
  1681  type MachineWithCharmsSuite struct {
  1682  	commonMachineSuite
  1683  	charmtesting.CharmSuite
  1684  
  1685  	machine *state.Machine
  1686  }
  1687  
  1688  func (s *MachineWithCharmsSuite) SetUpSuite(c *gc.C) {
  1689  	s.commonMachineSuite.SetUpSuite(c)
  1690  	s.CharmSuite.SetUpSuite(c, &s.commonMachineSuite.JujuConnSuite)
  1691  }
  1692  
  1693  func (s *MachineWithCharmsSuite) TearDownSuite(c *gc.C) {
  1694  	s.CharmSuite.TearDownSuite(c)
  1695  	s.commonMachineSuite.TearDownSuite(c)
  1696  }
  1697  
  1698  func (s *MachineWithCharmsSuite) SetUpTest(c *gc.C) {
  1699  	s.commonMachineSuite.SetUpTest(c)
  1700  	s.CharmSuite.SetUpTest(c)
  1701  }
  1702  
  1703  func (s *MachineWithCharmsSuite) TearDownTest(c *gc.C) {
  1704  	s.CharmSuite.TearDownTest(c)
  1705  	s.commonMachineSuite.TearDownTest(c)
  1706  }
  1707  
  1708  func (s *MachineWithCharmsSuite) TestManageModelRunsCharmRevisionUpdater(c *gc.C) {
  1709  	m, _, _ := s.primeAgent(c, state.JobManageModel)
  1710  
  1711  	s.SetupScenario(c)
  1712  
  1713  	a := s.newAgent(c, m)
  1714  	go func() {
  1715  		c.Check(a.Run(nil), jc.ErrorIsNil)
  1716  	}()
  1717  	defer func() { c.Check(a.Stop(), jc.ErrorIsNil) }()
  1718  
  1719  	checkRevision := func() bool {
  1720  		curl := charm.MustParseURL("cs:quantal/mysql")
  1721  		placeholder, err := s.State.LatestPlaceholderCharm(curl)
  1722  		return err == nil && placeholder.String() == curl.WithRevision(23).String()
  1723  	}
  1724  	success := false
  1725  	for attempt := coretesting.LongAttempt.Start(); attempt.Next(); {
  1726  		if success = checkRevision(); success {
  1727  			break
  1728  		}
  1729  	}
  1730  	c.Assert(success, jc.IsTrue)
  1731  }
  1732  
  1733  type mongoSuite struct {
  1734  	coretesting.BaseSuite
  1735  }
  1736  
  1737  func (s *mongoSuite) TestStateWorkerDialSetsWriteMajority(c *gc.C) {
  1738  	s.testStateWorkerDialSetsWriteMajority(c, true)
  1739  }
  1740  
  1741  func (s *mongoSuite) TestStateWorkerDialDoesNotSetWriteMajorityWithoutReplsetConfig(c *gc.C) {
  1742  	s.testStateWorkerDialSetsWriteMajority(c, false)
  1743  }
  1744  
  1745  func (s *mongoSuite) testStateWorkerDialSetsWriteMajority(c *gc.C, configureReplset bool) {
  1746  	inst := gitjujutesting.MgoInstance{
  1747  		EnableJournal: true,
  1748  		Params:        []string{"--replSet", "juju"},
  1749  	}
  1750  	err := inst.Start(coretesting.Certs)
  1751  	c.Assert(err, jc.ErrorIsNil)
  1752  	defer inst.Destroy()
  1753  
  1754  	var expectedWMode string
  1755  	dialOpts := stateWorkerDialOpts
  1756  	dialOpts.Timeout = coretesting.LongWait
  1757  	if configureReplset {
  1758  		info := inst.DialInfo()
  1759  		info.Timeout = dialOpts.Timeout
  1760  		args := peergrouper.InitiateMongoParams{
  1761  			DialInfo:       info,
  1762  			MemberHostPort: inst.Addr(),
  1763  		}
  1764  		err = peergrouper.InitiateMongoServer(args)
  1765  		c.Assert(err, jc.ErrorIsNil)
  1766  		expectedWMode = "majority"
  1767  	} else {
  1768  		dialOpts.Direct = true
  1769  	}
  1770  
  1771  	mongoInfo := mongo.Info{
  1772  		Addrs:  []string{inst.Addr()},
  1773  		CACert: coretesting.CACert,
  1774  	}
  1775  	session, err := mongo.DialWithInfo(mongoInfo, dialOpts)
  1776  	c.Assert(err, jc.ErrorIsNil)
  1777  	defer session.Close()
  1778  
  1779  	safe := session.Safe()
  1780  	c.Assert(safe, gc.NotNil)
  1781  	c.Assert(safe.WMode, gc.Equals, expectedWMode)
  1782  	c.Assert(safe.J, jc.IsTrue) // always enabled
  1783  }
  1784  
  1785  type mockAgentConfig struct {
  1786  	agent.Config
  1787  	providerType string
  1788  	tag          names.Tag
  1789  }
  1790  
  1791  func (m *mockAgentConfig) Tag() names.Tag {
  1792  	return m.tag
  1793  }
  1794  
  1795  func (m *mockAgentConfig) Value(key string) string {
  1796  	if key == agent.ProviderType {
  1797  		return m.providerType
  1798  	}
  1799  	return ""
  1800  }
  1801  
  1802  type singularRunnerRecord struct {
  1803  	runnerC chan *fakeSingularRunner
  1804  }
  1805  
  1806  func newSingularRunnerRecord() *singularRunnerRecord {
  1807  	return &singularRunnerRecord{
  1808  		runnerC: make(chan *fakeSingularRunner, 64),
  1809  	}
  1810  }
  1811  
  1812  func (r *singularRunnerRecord) newSingularRunner(runner worker.Runner, conn singular.Conn) (worker.Runner, error) {
  1813  	sr, err := singular.New(runner, conn)
  1814  	if err != nil {
  1815  		return nil, err
  1816  	}
  1817  	fakeRunner := &fakeSingularRunner{
  1818  		Runner: sr,
  1819  		startC: make(chan string, 64),
  1820  	}
  1821  	r.runnerC <- fakeRunner
  1822  	return fakeRunner, nil
  1823  }
  1824  
  1825  // nextRunner blocks until a new singular runner is created.
  1826  func (r *singularRunnerRecord) nextRunner(c *gc.C) *fakeSingularRunner {
  1827  	timeout := time.After(coretesting.LongWait)
  1828  	for {
  1829  		select {
  1830  		case r := <-r.runnerC:
  1831  			return r
  1832  		case <-timeout:
  1833  			c.Fatal("timed out waiting for singular runner to be created")
  1834  		}
  1835  	}
  1836  }
  1837  
  1838  type fakeSingularRunner struct {
  1839  	worker.Runner
  1840  	startC chan string
  1841  }
  1842  
  1843  func (r *fakeSingularRunner) StartWorker(name string, start func() (worker.Worker, error)) error {
  1844  	logger.Infof("starting fake worker %q", name)
  1845  	r.startC <- name
  1846  	return r.Runner.StartWorker(name, start)
  1847  }
  1848  
  1849  // waitForWorker waits for a given worker to be started, returning all
  1850  // workers started while waiting.
  1851  func (r *fakeSingularRunner) waitForWorker(c *gc.C, target string) []string {
  1852  	var seen []string
  1853  	timeout := time.After(coretesting.LongWait)
  1854  	for {
  1855  		select {
  1856  		case <-time.After(coretesting.ShortWait):
  1857  			c.Logf("still waiting for %q; workers seen so far: %+v", target, seen)
  1858  		case workerName := <-r.startC:
  1859  			seen = append(seen, workerName)
  1860  			if workerName == target {
  1861  				c.Logf("target worker %q started; workers seen so far: %+v", workerName, seen)
  1862  				return seen
  1863  			}
  1864  			c.Logf("worker %q started; still waiting for %q; workers seen so far: %+v", workerName, target, seen)
  1865  		case <-timeout:
  1866  			c.Fatal("timed out waiting for " + target)
  1867  		}
  1868  	}
  1869  }
  1870  
  1871  // waitForWorkers waits for a given worker to be started, returning all
  1872  // workers started while waiting.
  1873  func (r *fakeSingularRunner) waitForWorkers(c *gc.C, targets []string) []string {
  1874  	var seen []string
  1875  	seenTargets := make(map[string]bool)
  1876  	numSeenTargets := 0
  1877  	timeout := time.After(coretesting.LongWait)
  1878  	for {
  1879  		select {
  1880  		case workerName := <-r.startC:
  1881  			c.Logf("worker %q started; workers seen so far: %+v (len: %d, len(targets): %d)", workerName, seen, len(seen), len(targets))
  1882  			if seenTargets[workerName] == true {
  1883  				c.Fatal("worker started twice: " + workerName)
  1884  			}
  1885  			seenTargets[workerName] = true
  1886  			numSeenTargets++
  1887  			seen = append(seen, workerName)
  1888  			if numSeenTargets == len(targets) {
  1889  				c.Logf("all expected target workers started: %+v", seen)
  1890  				return seen
  1891  			}
  1892  			c.Logf("still waiting for workers %+v to start; numSeenTargets=%d", targets, numSeenTargets)
  1893  		case <-timeout:
  1894  			c.Fatalf("timed out waiting for %v", targets)
  1895  		}
  1896  	}
  1897  }
  1898  
  1899  type mockMetricAPI struct {
  1900  	stop          chan struct{}
  1901  	cleanUpCalled chan struct{}
  1902  	sendCalled    chan struct{}
  1903  }
  1904  
  1905  func newMockMetricAPI() *mockMetricAPI {
  1906  	return &mockMetricAPI{
  1907  		stop:          make(chan struct{}),
  1908  		cleanUpCalled: make(chan struct{}),
  1909  		sendCalled:    make(chan struct{}),
  1910  	}
  1911  }
  1912  
  1913  func (m *mockMetricAPI) CleanupOldMetrics() error {
  1914  	go func() {
  1915  		select {
  1916  		case m.cleanUpCalled <- struct{}{}:
  1917  		case <-m.stop:
  1918  			break
  1919  		}
  1920  	}()
  1921  	return nil
  1922  }
  1923  
  1924  func (m *mockMetricAPI) SendMetrics() error {
  1925  	go func() {
  1926  		select {
  1927  		case m.sendCalled <- struct{}{}:
  1928  		case <-m.stop:
  1929  			break
  1930  		}
  1931  	}()
  1932  	return nil
  1933  }
  1934  
  1935  func (m *mockMetricAPI) SendCalled() <-chan struct{} {
  1936  	return m.sendCalled
  1937  }
  1938  
  1939  func (m *mockMetricAPI) CleanupCalled() <-chan struct{} {
  1940  	return m.cleanUpCalled
  1941  }
  1942  
  1943  func (m *mockMetricAPI) Stop() {
  1944  	close(m.stop)
  1945  }
  1946  
  1947  type mockLoopDeviceManager struct {
  1948  	detachLoopDevicesArgRootfs string
  1949  	detachLoopDevicesArgPrefix string
  1950  }
  1951  
  1952  func (m *mockLoopDeviceManager) DetachLoopDevices(rootfs, prefix string) error {
  1953  	m.detachLoopDevicesArgRootfs = rootfs
  1954  	m.detachLoopDevicesArgPrefix = prefix
  1955  	return nil
  1956  }
  1957  
  1958  func newSignal() *signal {
  1959  	return &signal{ch: make(chan struct{})}
  1960  }
  1961  
  1962  type signal struct {
  1963  	mu sync.Mutex
  1964  	ch chan struct{}
  1965  }
  1966  
  1967  func (s *signal) triggered() <-chan struct{} {
  1968  	return s.ch
  1969  }
  1970  
  1971  func (s *signal) assertTriggered(c *gc.C, thing string) {
  1972  	select {
  1973  	case <-s.triggered():
  1974  	case <-time.After(coretesting.LongWait):
  1975  		c.Fatalf("timed out waiting for " + thing)
  1976  	}
  1977  }
  1978  
  1979  func (s *signal) assertNotTriggered(c *gc.C, wait time.Duration, thing string) {
  1980  	select {
  1981  	case <-s.triggered():
  1982  		c.Fatalf("%v unexpectedly", thing)
  1983  	case <-time.After(wait):
  1984  	}
  1985  }
  1986  
  1987  func (s *signal) trigger() {
  1988  	s.mu.Lock()
  1989  	defer s.mu.Unlock()
  1990  
  1991  	select {
  1992  	case <-s.ch:
  1993  		// Already closed.
  1994  	default:
  1995  		close(s.ch)
  1996  	}
  1997  }