func (s *UpgraderSuite) TestUpgraderRetryAndChanged(c *gc.C) { stor := s.Conn.Environ.Storage() oldTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64")) s.PatchValue(&version.Current, oldTools.Version) newTools := envtesting.AssertUploadFakeToolsVersions( c, stor, version.MustParseBinary("5.4.5-precise-amd64"))[0] err := statetesting.SetAgentVersion(s.State, newTools.Version.Number) c.Assert(err, gc.IsNil) retryc := make(chan time.Time) *upgrader.RetryAfter = func() <-chan time.Time { c.Logf("replacement retry after") return retryc } dummy.Poison(s.Conn.Environ.Storage(), envtools.StorageName(newTools.Version), fmt.Errorf("a non-fatal dose")) u := s.makeUpgrader() defer u.Stop() for i := 0; i < 3; i++ { select { case retryc <- time.Now(): case <-time.After(coretesting.LongWait): c.Fatalf("upgrader did not retry (attempt %d)", i) } } // Make it upgrade to some newer tools that can be // downloaded ok; it should stop retrying, download // the newer tools and exit. newerTools := envtesting.AssertUploadFakeToolsVersions( c, s.Conn.Environ.Storage(), version.MustParseBinary("5.4.6-precise-amd64"))[0] err = statetesting.SetAgentVersion(s.State, newerTools.Version.Number) c.Assert(err, gc.IsNil) s.BackingState.StartSync() done := make(chan error) go func() { done <- u.Wait() }() select { case err := <-done: envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{ AgentName: s.machine.Tag(), OldTools: oldTools.Version, NewTools: newerTools.Version, DataDir: s.DataDir(), }) case <-time.After(coretesting.LongWait): c.Fatalf("upgrader did not quit after upgrading") } }
func (s *UpgraderSuite) TestUpgraderUpgradesImmediately(c *gc.C) { stor := s.Conn.Environ.Storage() oldTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64")) s.PatchValue(&version.Current, oldTools.Version) newTools := envtesting.AssertUploadFakeToolsVersions( c, stor, version.MustParseBinary("5.4.5-precise-amd64"))[0] err := statetesting.SetAgentVersion(s.State, newTools.Version.Number) c.Assert(err, gc.IsNil) // Make the download take a while so that we verify that // the download happens before the upgrader checks if // it's been stopped. dummy.SetStorageDelay(coretesting.ShortWait) u := s.makeUpgrader() err = u.Stop() envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{ AgentName: s.machine.Tag(), OldTools: oldTools.Version, NewTools: newTools.Version, DataDir: s.DataDir(), }) foundTools, err := agenttools.ReadTools(s.DataDir(), newTools.Version) c.Assert(err, gc.IsNil) envtesting.CheckTools(c, foundTools, newTools) }
func (s *MachineSuite) TestManageEnviron(c *gc.C) { usefulVersion := version.Current usefulVersion.Series = "quantal" // to match the charm created below envtesting.AssertUploadFakeToolsVersions(c, s.Conn.Environ.Storage(), usefulVersion) m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron) op := make(chan dummy.Operation, 200) dummy.Listen(op) a := s.newAgent(c, m) // Make sure the agent is stopped even if the test fails. defer a.Stop() done := make(chan error) go func() { done <- a.Run(nil) }() // Check that the provisioner and firewaller are alive by doing // a rudimentary check that it responds to state changes. // Add one unit to a service; it should get allocated a machine // and then its ports should be opened. charm := s.AddTestingCharm(c, "dummy") svc := s.AddTestingService(c, "test-service", charm) err := svc.SetExposed() c.Assert(err, gc.IsNil) units, err := juju.AddUnits(s.State, svc, 1, "") c.Assert(err, gc.IsNil) c.Check(opRecvTimeout(c, s.State, op, dummy.OpStartInstance{}), gc.NotNil) // Wait for the instance id to show up in the state. s.waitProvisioned(c, units[0]) err = units[0].OpenPort("tcp", 999) c.Assert(err, gc.IsNil) c.Check(opRecvTimeout(c, s.State, op, dummy.OpOpenPorts{}), gc.NotNil) err = a.Stop() c.Assert(err, gc.IsNil) select { case err := <-done: c.Assert(err, gc.IsNil) case <-time.After(5 * time.Second): c.Fatalf("timed out waiting for agent to terminate") } c.Assert(s.singularRecord.started(), jc.DeepEquals, []string{ "charm-revision-updater", "cleaner", "environ-provisioner", "firewaller", "minunitsworker", "resumer", }) }
func (s *bootstrapSuite) TestBootstrapTools(c *gc.C) { allTests := append(envtesting.BootstrapToolsTests, bootstrapSetAgentVersionTests...) // version.Current is set in the loop so ensure it is restored later. s.PatchValue(&version.Current, version.Current) for i, test := range allTests { c.Logf("\ntest %d: %s", i, test.Info) dummy.Reset() attrs := dummy.SampleConfig().Merge(coretesting.Attrs{ "state-server": false, "development": test.Development, "default-series": test.DefaultSeries, }) if test.AgentVersion != version.Zero { attrs["agent-version"] = test.AgentVersion.String() } cfg, err := config.New(config.NoDefaults, attrs) c.Assert(err, gc.IsNil) env, err := environs.Prepare(cfg, coretesting.Context(c), configstore.NewMem()) c.Assert(err, gc.IsNil) envtesting.RemoveAllTools(c, env) version.Current = test.CliVersion envtesting.AssertUploadFakeToolsVersions(c, env.Storage(), test.Available...) // Remove the default tools URL from the search path, just look in cloud storage. s.PatchValue(&envtools.DefaultBaseURL, "") cons := constraints.Value{} if test.Arch != "" { cons = constraints.MustParse("arch=" + test.Arch) } err = bootstrap.Bootstrap(coretesting.Context(c), env, environs.BootstrapParams{Constraints: cons}) if test.Err != "" { c.Check(err, gc.NotNil) if err != nil { stripped := strings.Replace(err.Error(), "\n", "", -1) c.Check(stripped, gc.Matches, ".*"+stripped) } continue } else { c.Check(err, gc.IsNil) } unique := map[version.Number]bool{} for _, expected := range test.Expect { unique[expected.Number] = true } for expectAgentVersion := range unique { agentVersion, ok := env.Config().AgentVersion() c.Check(ok, gc.Equals, true) c.Check(agentVersion, gc.Equals, expectAgentVersion) } } }
func (s *MachineSuite) testUpgradeRequest(c *gc.C, agent runner, tag string, currentTools *tools.Tools) { newVers := version.Current newVers.Patch++ newTools := envtesting.AssertUploadFakeToolsVersions(c, s.Conn.Environ.Storage(), newVers)[0] err := s.State.SetEnvironAgentVersion(newVers.Number) c.Assert(err, gc.IsNil) err = runWithTimeout(agent) envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{ AgentName: tag, OldTools: currentTools.Version, NewTools: newTools.Version, DataDir: s.DataDir(), }) }
func (s *UnitSuite) TestUpgrade(c *gc.C) { machine, unit, _, currentTools := s.primeAgent(c) agent := s.newAgent(c, unit) newVers := version.Current newVers.Patch++ envtesting.AssertUploadFakeToolsVersions(c, s.Conn.Environ.Storage(), newVers) // Set the machine agent version to trigger an upgrade. err := machine.SetAgentVersion(newVers) c.Assert(err, gc.IsNil) err = runWithTimeout(agent) envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{ AgentName: unit.Tag(), OldTools: currentTools.Version, NewTools: newVers, DataDir: s.DataDir(), }) }
func (s *StorageSuite) TestReadList(c *gc.C) { store := s.env.Storage() v001 := version.MustParseBinary("0.0.1-precise-amd64") v100 := version.MustParseBinary("1.0.0-precise-amd64") v101 := version.MustParseBinary("1.0.1-precise-amd64") v111 := version.MustParseBinary("1.1.1-precise-amd64") agentTools := envtesting.AssertUploadFakeToolsVersions(c, store, v001, v100, v101, v111) t001 := agentTools[0] t100 := agentTools[1] t101 := agentTools[2] t111 := agentTools[3] for i, t := range []struct { majorVersion, minorVersion int list coretools.List }{{ 0, 0, coretools.List{t001}, }, { 1, 0, coretools.List{t100, t101}, }, { 1, 1, coretools.List{t111}, }, { 1, -1, coretools.List{t100, t101, t111}, }, { 1, 2, nil, }, { 2, 0, nil, }} { c.Logf("test %d", i) list, err := envtools.ReadList(store, t.majorVersion, t.minorVersion) if t.list != nil { c.Assert(err, gc.IsNil) // ReadList doesn't set the Size of SHA256, so blank out those attributes. for _, tool := range t.list { tool.Size = 0 tool.SHA256 = "" } c.Assert(list, gc.DeepEquals, t.list) } else { c.Assert(err, gc.Equals, coretools.ErrNoMatches) } } }
// Check that we get a consistent error when asking for an instance without // a valid machine config. func (t *LiveTests) TestStartInstanceWithEmptyNonceFails(c *gc.C) { machineId := "4" stateInfo := testing.FakeStateInfo(machineId) apiInfo := testing.FakeAPIInfo(machineId) machineConfig := environs.NewMachineConfig(machineId, "", nil, nil, stateInfo, apiInfo) t.PrepareOnce(c) possibleTools := envtesting.AssertUploadFakeToolsVersions(c, t.Env.Storage(), version.MustParseBinary("5.4.5-precise-amd64")) inst, _, _, err := t.Env.StartInstance(environs.StartInstanceParams{ Tools: possibleTools, MachineConfig: machineConfig, }) if inst != nil { err := t.Env.StopInstances([]instance.Instance{inst}) c.Check(err, gc.IsNil) } c.Assert(inst, gc.IsNil) c.Assert(err, gc.ErrorMatches, ".*missing machine nonce") }
func (s *UpgraderSuite) TestUpgraderRefusesToDowngradeMinorVersions(c *gc.C) { stor := s.Conn.Environ.Storage() origTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64")) s.PatchValue(&version.Current, origTools.Version) downgradeTools := envtesting.AssertUploadFakeToolsVersions( c, stor, version.MustParseBinary("5.3.3-precise-amd64"))[0] err := statetesting.SetAgentVersion(s.State, downgradeTools.Version.Number) c.Assert(err, gc.IsNil) u := s.makeUpgrader() err = u.Stop() // If the upgrade would have triggered, we would have gotten an // UpgradeReadyError, since it was skipped, we get no error c.Check(err, gc.IsNil) _, err = agenttools.ReadTools(s.DataDir(), downgradeTools.Version) // TODO: ReadTools *should* be returning some form of errors.NotFound, // however, it just passes back a fmt.Errorf so we live with it // c.Assert(err, jc.Satisfies, errors.IsNotFound) c.Check(err, gc.ErrorMatches, "cannot read tools metadata in tools directory.*no such file or directory") }
func (s *MachineSuite) TestManageEnvironCallsUseMultipleCPUs(c *gc.C) { // If it has been enabled, the JobManageEnviron agent should call utils.UseMultipleCPUs usefulVersion := version.Current usefulVersion.Series = "quantal" envtesting.AssertUploadFakeToolsVersions(c, s.Conn.Environ.Storage(), usefulVersion) m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron) calledChan := make(chan struct{}, 1) s.PatchValue(&useMultipleCPUs, func() { calledChan <- struct{}{} }) // Now, start the agent, and observe that a JobManageEnviron agent // calls UseMultipleCPUs a := s.newAgent(c, m) defer a.Stop() go func() { c.Check(a.Run(nil), gc.IsNil) }() // Wait for configuration to be finished <-a.WorkersStarted() select { case <-calledChan: case <-time.After(coretesting.LongWait): c.Errorf("we failed to call UseMultipleCPUs()") } c.Check(a.Stop(), gc.IsNil) // However, an agent that just JobHostUnits doesn't call UseMultipleCPUs m2, _, _ := s.primeAgent(c, version.Current, state.JobHostUnits) a2 := s.newAgent(c, m2) defer a2.Stop() go func() { c.Check(a2.Run(nil), gc.IsNil) }() // Wait until all the workers have been started, and then kill everything <-a2.workersStarted c.Check(a2.Stop(), gc.IsNil) select { case <-calledChan: c.Errorf("we should not have called UseMultipleCPUs()") case <-time.After(coretesting.ShortWait): } }
func (s *MachineSuite) TestManageEnvironRunsInstancePoller(c *gc.C) { s.PatchValue(&instancepoller.ShortPoll, 500*time.Millisecond) usefulVersion := version.Current usefulVersion.Series = "quantal" // to match the charm created below envtesting.AssertUploadFakeToolsVersions(c, s.Conn.Environ.Storage(), usefulVersion) m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron) a := s.newAgent(c, m) defer a.Stop() go func() { c.Check(a.Run(nil), gc.IsNil) }() // Add one unit to a service; charm := s.AddTestingCharm(c, "dummy") svc := s.AddTestingService(c, "test-service", charm) units, err := juju.AddUnits(s.State, svc, 1, "") c.Assert(err, gc.IsNil) m, instId := s.waitProvisioned(c, units[0]) insts, err := s.Conn.Environ.Instances([]instance.Id{instId}) c.Assert(err, gc.IsNil) addrs := []instance.Address{instance.NewAddress("1.2.3.4", instance.NetworkUnknown)} dummy.SetInstanceAddresses(insts[0], addrs) dummy.SetInstanceStatus(insts[0], "running") for a := coretesting.LongAttempt.Start(); a.Next(); { if !a.HasNext() { c.Logf("final machine addresses: %#v", m.Addresses()) c.Fatalf("timed out waiting for machine to get address") } err := m.Refresh() c.Assert(err, gc.IsNil) instStatus, err := m.InstanceStatus() c.Assert(err, gc.IsNil) if reflect.DeepEqual(m.Addresses(), addrs) && instStatus == "running" { break } } }
func (s *UpgraderSuite) TestUpgraderAllowsDowngradingPatchVersions(c *gc.C) { stor := s.Conn.Environ.Storage() origTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64")) s.PatchValue(&version.Current, origTools.Version) downgradeTools := envtesting.AssertUploadFakeToolsVersions( c, stor, version.MustParseBinary("5.4.2-precise-amd64"))[0] err := statetesting.SetAgentVersion(s.State, downgradeTools.Version.Number) c.Assert(err, gc.IsNil) dummy.SetStorageDelay(coretesting.ShortWait) u := s.makeUpgrader() err = u.Stop() envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{ AgentName: s.machine.Tag(), OldTools: origTools.Version, NewTools: downgradeTools.Version, DataDir: s.DataDir(), }) foundTools, err := agenttools.ReadTools(s.DataDir(), downgradeTools.Version) c.Assert(err, gc.IsNil) envtesting.CheckTools(c, foundTools, downgradeTools) }
func (s *provisionerSuite) TestProvisionMachine(c *gc.C) { const series = "precise" const arch = "amd64" args := s.getArgs(c) hostname := args.Host args.Host = "ubuntu@" + args.Host envtesting.RemoveTools(c, s.Conn.Environ.Storage()) defer fakeSSH{ Series: series, Arch: arch, InitUbuntuUser: true, SkipProvisionAgent: true, }.install(c).Restore() // Attempt to provision a machine with no tools available, expect it to fail. machineId, err := manual.ProvisionMachine(args) c.Assert(err, jc.Satisfies, params.IsCodeNotFound) c.Assert(machineId, gc.Equals, "") cfg := s.Conn.Environ.Config() number, ok := cfg.AgentVersion() c.Assert(ok, jc.IsTrue) binVersion := version.Binary{number, series, arch} envtesting.AssertUploadFakeToolsVersions(c, s.Conn.Environ.Storage(), binVersion) for i, errorCode := range []int{255, 0} { c.Logf("test %d: code %d", i, errorCode) defer fakeSSH{ Series: series, Arch: arch, InitUbuntuUser: true, ProvisionAgentExitCode: errorCode, }.install(c).Restore() machineId, err = manual.ProvisionMachine(args) if errorCode != 0 { c.Assert(err, gc.ErrorMatches, fmt.Sprintf("subprocess encountered error code %d", errorCode)) c.Assert(machineId, gc.Equals, "") } else { c.Assert(err, gc.IsNil) c.Assert(machineId, gc.Not(gc.Equals), "") // machine ID will be incremented. Even though we failed and the // machine is removed, the ID is not reused. c.Assert(machineId, gc.Equals, fmt.Sprint(i+1)) m, err := s.State.Machine(machineId) c.Assert(err, gc.IsNil) instanceId, err := m.InstanceId() c.Assert(err, gc.IsNil) c.Assert(instanceId, gc.Equals, instance.Id("manual:"+hostname)) } } // Attempting to provision a machine twice should fail. We effect // this by checking for existing juju upstart configurations. defer fakeSSH{ Provisioned: true, InitUbuntuUser: true, SkipDetection: true, SkipProvisionAgent: true, }.install(c).Restore() _, err = manual.ProvisionMachine(args) c.Assert(err, gc.Equals, manual.ErrProvisioned) defer fakeSSH{ Provisioned: true, CheckProvisionedExitCode: 255, InitUbuntuUser: true, SkipDetection: true, SkipProvisionAgent: true, }.install(c).Restore() _, err = manual.ProvisionMachine(args) c.Assert(err, gc.ErrorMatches, "error checking if provisioned: subprocess encountered error code 255") }
func (test bootstrapTest) run(c *gc.C) { // Create home with dummy provider and remove all // of its envtools. env, fake := makeEmptyFakeHome(c) defer fake.Restore() if test.version != "" { useVersion := strings.Replace(test.version, "%LTS%", config.LatestLtsSeries(), 1) origVersion := version.Current version.Current = version.MustParseBinary(useVersion) defer func() { version.Current = origVersion }() } if test.hostArch != "" { origVersion := arch.HostArch arch.HostArch = func() string { return test.hostArch } defer func() { arch.HostArch = origVersion }() } uploadCount := len(test.uploads) if uploadCount == 0 { usefulVersion := version.Current usefulVersion.Series = config.PreferredSeries(env.Config()) envtesting.AssertUploadFakeToolsVersions(c, env.Storage(), usefulVersion) } // Run command and check for uploads. opc, errc := runCommand(nullContext(c), new(BootstrapCommand), test.args...) // Check for remaining operations/errors. if test.err != "" { err := <-errc stripped := strings.Replace(err.Error(), "\n", "", -1) c.Check(stripped, gc.Matches, test.err) return } if !c.Check(<-errc, gc.IsNil) { return } if uploadCount > 0 { for i := 0; i < uploadCount; i++ { c.Check((<-opc).(dummy.OpPutFile).Env, gc.Equals, "peckham") } list, err := envtools.FindTools( env, version.Current.Major, version.Current.Minor, coretools.Filter{}, envtools.DoNotAllowRetry) c.Check(err, gc.IsNil) c.Logf("found: " + list.String()) urls := list.URLs() c.Check(urls, gc.HasLen, len(test.uploads)) for _, v := range test.uploads { v := strings.Replace(v, "%LTS%", config.LatestLtsSeries(), 1) c.Logf("seeking: " + v) vers := version.MustParseBinary(v) _, found := urls[vers] c.Check(found, gc.Equals, true) } } if len(test.uploads) > 0 { indexFile := (<-opc).(dummy.OpPutFile) c.Check(indexFile.FileName, gc.Equals, "tools/streams/v1/index.json") productFile := (<-opc).(dummy.OpPutFile) c.Check(productFile.FileName, gc.Equals, "tools/streams/v1/com.ubuntu.juju:released:tools.json") } opPutBootstrapVerifyFile := (<-opc).(dummy.OpPutFile) c.Check(opPutBootstrapVerifyFile.Env, gc.Equals, "peckham") c.Check(opPutBootstrapVerifyFile.FileName, gc.Equals, environs.VerificationFilename) opPutBootstrapInitFile := (<-opc).(dummy.OpPutFile) c.Check(opPutBootstrapInitFile.Env, gc.Equals, "peckham") c.Check(opPutBootstrapInitFile.FileName, gc.Equals, "provider-state") opBootstrap := (<-opc).(dummy.OpBootstrap) c.Check(opBootstrap.Env, gc.Equals, "peckham") c.Check(opBootstrap.Args.Constraints, gc.DeepEquals, test.constraints) c.Check(opBootstrap.Args.Placement, gc.Equals, test.placement) store, err := configstore.Default() c.Assert(err, gc.IsNil) // Check a CA cert/key was generated by reloading the environment. env, err = environs.NewFromName("peckham", store) c.Assert(err, gc.IsNil) _, hasCert := env.Config().CACert() c.Check(hasCert, gc.Equals, true) _, hasKey := env.Config().CAPrivateKey() c.Check(hasKey, gc.Equals, true) }
func uploadTools(c *gc.C, env environs.Environ) { usefulVersion := version.Current usefulVersion.Series = config.PreferredSeries(env.Config()) envtesting.AssertUploadFakeToolsVersions(c, env.Storage(), usefulVersion) }