func (s *UpgraderSuite) TestUpgraderRetryAndChanged(c *gc.C) { stor := s.DefaultToolsStorage oldTools := envtesting.PrimeTools(c, stor, s.DataDir(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.3-precise-amd64")) s.PatchValue(&version.Current, oldTools.Version) newTools := envtesting.AssertUploadFakeToolsVersions( c, stor, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.5-precise-amd64"))[0] err := statetesting.SetAgentVersion(s.State, newTools.Version.Number) c.Assert(err, jc.ErrorIsNil) retryc := make(chan time.Time) *upgrader.RetryAfter = func() <-chan time.Time { c.Logf("replacement retry after") return retryc } err = stor.Remove(envtools.StorageName(newTools.Version, "released")) c.Assert(err, jc.ErrorIsNil) u := s.makeUpgrader(c) defer u.Stop() s.expectUpgradeChannelNotClosed(c) 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, stor, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.6-precise-amd64"))[0] err = statetesting.SetAgentVersion(s.State, newerTools.Version.Number) c.Assert(err, jc.ErrorIsNil) 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().String(), OldTools: oldTools.Version, NewTools: newerTools.Version, DataDir: s.DataDir(), }) case <-time.After(coretesting.LongWait): c.Fatalf("upgrader did not quit after upgrading") } }
// 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 := jujutesting.FakeStateInfo(machineId) apiInfo := jujutesting.FakeAPIInfo(machineId) instanceConfig, err := instancecfg.NewInstanceConfig(machineId, "", "released", "quantal", "", true, nil, stateInfo, apiInfo) c.Assert(err, jc.ErrorIsNil) t.PrepareOnce(c) possibleTools := coretools.List(envtesting.AssertUploadFakeToolsVersions( c, t.toolsStorage, "released", "released", version.MustParseBinary("5.4.5-trusty-amd64"), )) params := environs.StartInstanceParams{ Tools: possibleTools, InstanceConfig: instanceConfig, } err = jujutesting.SetImageMetadata( t.Env, possibleTools.AllSeries(), possibleTools.Arches(), ¶ms.ImageMetadata, ) c.Check(err, jc.ErrorIsNil) result, err := t.Env.StartInstance(params) if result != nil && result.Instance != nil { err := t.Env.StopInstances(result.Instance.Id()) c.Check(err, jc.ErrorIsNil) } c.Assert(result, gc.IsNil) c.Assert(err, gc.ErrorMatches, ".*missing machine nonce") }
func (s *UpgraderSuite) TestUpgraderAllowsDowngradeToOrigVersionIfUpgradeInProgress(c *gc.C) { // note: otherwise illegal version jump downgradeVersion := version.MustParseBinary("5.3.0-precise-amd64") s.confVersion = downgradeVersion.Number s.upgradeRunning = true stor := s.DefaultToolsStorage origTools := envtesting.PrimeTools(c, stor, s.DataDir(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.3-precise-amd64")) s.PatchValue(&version.Current, origTools.Version) downgradeTools := envtesting.AssertUploadFakeToolsVersions( c, stor, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), downgradeVersion)[0] err := statetesting.SetAgentVersion(s.State, downgradeVersion.Number) c.Assert(err, jc.ErrorIsNil) dummy.SetStorageDelay(coretesting.ShortWait) u := s.makeUpgrader(c) err = u.Stop() s.expectUpgradeChannelNotClosed(c) envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{ AgentName: s.machine.Tag().String(), OldTools: origTools.Version, NewTools: downgradeVersion, DataDir: s.DataDir(), }) foundTools, err := agenttools.ReadTools(s.DataDir(), downgradeTools.Version) c.Assert(err, jc.ErrorIsNil) downgradeTools.URL = fmt.Sprintf("https://%s/environment/%s/tools/5.3.0-precise-amd64", s.APIState.Addr(), coretesting.EnvironmentTag.Id()) envtesting.CheckTools(c, foundTools, downgradeTools) }
func (s *UpgraderSuite) TestUpgraderUpgradesImmediately(c *gc.C) { stor := s.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().String(), 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 *UnitSuite) TestUpgrade(c *gc.C) { machine, unit, _, currentTools := s.primeAgent(c) agent := s.newAgent(c, unit) newVers := version.Binary{ Number: version.Current, Arch: arch.HostArch(), Series: series.HostSeries(), } newVers.Patch++ envtesting.AssertUploadFakeToolsVersions( c, s.DefaultToolsStorage, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), newVers) // The machine agent downloads the tools; fake this by // creating downloaded-tools.txt in data-dir/tools/<version>. toolsDir := agenttools.SharedToolsDir(s.DataDir(), newVers) err := os.MkdirAll(toolsDir, 0755) c.Assert(err, jc.ErrorIsNil) toolsPath := filepath.Join(toolsDir, "downloaded-tools.txt") testTools := tools.Tools{Version: newVers, URL: "http://testing.invalid/tools"} data, err := json.Marshal(testTools) c.Assert(err, jc.ErrorIsNil) err = ioutil.WriteFile(toolsPath, data, 0644) c.Assert(err, jc.ErrorIsNil) // Set the machine agent version to trigger an upgrade. err = machine.SetAgentVersion(newVers) c.Assert(err, jc.ErrorIsNil) err = runWithTimeout(agent) envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{ AgentName: unit.Tag().String(), OldTools: currentTools.Version, NewTools: newVers, DataDir: s.DataDir(), }) }
func (s *UpgraderSuite) TestUpgraderUpgradesImmediately(c *gc.C) { stor := s.DefaultToolsStorage oldTools := envtesting.PrimeTools(c, stor, s.DataDir(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.3-precise-amd64")) s.PatchValue(&version.Current, oldTools.Version) newTools := envtesting.AssertUploadFakeToolsVersions( c, stor, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.5-precise-amd64"))[0] err := statetesting.SetAgentVersion(s.State, newTools.Version.Number) c.Assert(err, jc.ErrorIsNil) // 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(c) err = u.Stop() s.expectUpgradeChannelNotClosed(c) envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{ AgentName: s.machine.Tag().String(), OldTools: oldTools.Version, NewTools: newTools.Version, DataDir: s.DataDir(), }) foundTools, err := agenttools.ReadTools(s.DataDir(), newTools.Version) c.Assert(err, jc.ErrorIsNil) newTools.URL = fmt.Sprintf("https://%s/environment/%s/tools/5.4.5-precise-amd64", s.APIState.Addr(), coretesting.EnvironmentTag.Id()) envtesting.CheckTools(c, foundTools, newTools) }
func (s *UpgradeSuite) TestDowngradeOnMasterWhenOtherStateServerDoesntStartUpgrade(c *gc.C) { coretesting.SkipIfWindowsBug(c, "lp:1446885") // This test checks that the master triggers a downgrade if one of // the other state server fails to signal it is ready for upgrade. // // This test is functional, ensuring that the upgrader worker // terminates the machine agent with the UpgradeReadyError which // makes the downgrade happen. // Speed up the watcher frequency to make the test much faster. s.PatchValue(&watcher.Period, 200*time.Millisecond) // Provide (fake) tools so that the upgrader has something to downgrade to. envtesting.AssertUploadFakeToolsVersions( c, s.DefaultToolsStorage, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), s.oldVersion) // Only the first machine is going to be ready for upgrade. machineIdA, machineIdB, _ := s.createUpgradingStateServers(c) // One of the other state servers is ready for upgrade (but machine C doesn't). info, err := s.State.EnsureUpgradeInfo(machineIdB, s.oldVersion.Number, version.Current) c.Assert(err, jc.ErrorIsNil) agent := s.newAgentFromMachineId(c, machineIdA) defer agent.Stop() s.machineIsMaster = true var agentErr error agentDone := make(chan bool) go func() { agentErr = agent.Run(nil) close(agentDone) }() select { case <-agentDone: upgradeReadyErr, ok := agentErr.(*upgrader.UpgradeReadyError) if !ok { c.Fatalf("didn't see UpgradeReadyError, instead got: %v", agentErr) } // Confirm that the downgrade is back to the previous version. current := version.Binary{ Number: version.Current, Arch: arch.HostArch(), Series: series.HostSeries(), } c.Assert(upgradeReadyErr.OldTools, gc.Equals, current) c.Assert(upgradeReadyErr.NewTools, gc.Equals, s.oldVersion) case <-time.After(coretesting.LongWait): c.Fatal("machine agent did not exit as expected") } // UpgradeInfo doc should now be archived. err = info.Refresh() c.Assert(err, gc.ErrorMatches, "current upgrade info not found") }
func (s *MachineSuite) TestManageModel(c *gc.C) { usefulVersion := version.Binary{ Number: jujuversion.Current, Arch: arch.HostArch(), Series: "quantal", // to match the charm created below } envtesting.AssertUploadFakeToolsVersions(c, s.DefaultToolsStorage, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), usefulVersion) m, _, _ := s.primeAgent(c, state.JobManageModel) 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) }() c.Logf("started test agent, waiting for workers...") r0 := s.singularRecord.nextRunner(c) r0.waitForWorker(c, "txnpruner") // Check that the provisioner and firewaller are alive by doing // a rudimentary check that it responds to state changes. // Create an exposed service, and add a unit. charm := s.AddTestingCharm(c, "dummy") svc := s.AddTestingService(c, "test-service", charm) err := svc.SetExposed() c.Assert(err, jc.ErrorIsNil) units, err := juju.AddUnits(s.State, svc, svc.Name(), 1, nil) c.Assert(err, jc.ErrorIsNil) // It should be allocated to a machine, which should then be provisioned. c.Logf("service %q added with 1 unit, waiting for unit %q's machine to be started...", svc.Name(), units[0].Name()) c.Check(opRecvTimeout(c, s.State, op, dummy.OpStartInstance{}), gc.NotNil) c.Logf("machine hosting unit %q started, waiting for the unit to be deployed...", units[0].Name()) s.waitProvisioned(c, units[0]) // Open a port on the unit; it should be handled by the firewaller. c.Logf("unit %q deployed, opening port tcp/999...", units[0].Name()) err = units[0].OpenPort("tcp", 999) c.Assert(err, jc.ErrorIsNil) c.Check(opRecvTimeout(c, s.State, op, dummy.OpOpenPorts{}), gc.NotNil) c.Logf("unit %q port tcp/999 opened, cleaning up...", units[0].Name()) err = a.Stop() c.Assert(err, jc.ErrorIsNil) select { case err := <-done: c.Assert(err, jc.ErrorIsNil) case <-time.After(coretesting.LongWait): c.Fatalf("timed out waiting for agent to terminate") } c.Logf("test agent stopped successfully.") }
func (s *MachineSuite) TestManageEnviron(c *gc.C) { usefulVersion := version.Current usefulVersion.Series = "quantal" // to match the charm created below envtesting.AssertUploadFakeToolsVersions(c, s.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 *lxcProvisionerSuite) maybeUploadTools(c *gc.C) { // The default series tools are already uploaded // for amd64 in the base suite. if arch.HostArch() == arch.AMD64 { return } storageDir := c.MkDir() s.CommonProvisionerSuite.PatchValue(&tools.DefaultBaseURL, storageDir) stor, err := filestorage.NewFileStorageWriter(storageDir) c.Assert(err, jc.ErrorIsNil) defaultTools := version.Binary{ Number: jujuversion.Current, Arch: arch.HostArch(), Series: coretesting.FakeDefaultSeries, } envtesting.AssertUploadFakeToolsVersions(c, stor, "devel", "devel", defaultTools) envtesting.AssertUploadFakeToolsVersions(c, stor, "released", "released", defaultTools) }
func (s *bootstrapSuite) TestBootstrapTools(c *gc.C) { s.PatchValue(&envtools.BundleTools, toolstesting.GetMockBundleTools(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 *toolsSuite) TestDownloadFetchesAndVerifiesSize(c *gc.C) { // Upload fake tools, then upload over the top so the SHA256 hash does not match. stor := s.Environ.Storage() envtesting.RemoveTools(c, stor) tools := envtesting.AssertUploadFakeToolsVersions(c, stor, version.Current)[0] err := stor.Put(envtools.StorageName(tools.Version), strings.NewReader("!"), 1) resp, err := s.downloadRequest(c, tools.Version, "") c.Assert(err, gc.IsNil) s.assertErrorResponse(c, resp, http.StatusBadRequest, "error fetching tools: size mismatch for .*") s.assertToolsNotStored(c, tools.Version) }
func (s *MachineSuite) TestManageModelRunsInstancePoller(c *gc.C) { s.AgentSuite.PatchValue(&instancepoller.ShortPoll, 500*time.Millisecond) usefulVersion := version.Binary{ Number: jujuversion.Current, Arch: arch.HostArch(), Series: "quantal", // to match the charm created below } envtesting.AssertUploadFakeToolsVersions( c, s.DefaultToolsStorage, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), usefulVersion, ) m, _, _ := s.primeAgent(c, state.JobManageModel) a := s.newAgent(c, m) defer a.Stop() go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }() // 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, svc.Name(), 1, nil) c.Assert(err, jc.ErrorIsNil) m, instId := s.waitProvisioned(c, units[0]) insts, err := s.Environ.Instances([]instance.Id{instId}) c.Assert(err, jc.ErrorIsNil) addrs := network.NewAddresses("1.2.3.4") dummy.SetInstanceAddresses(insts[0], addrs) dummy.SetInstanceStatus(insts[0], "running") for attempt := coretesting.LongAttempt.Start(); attempt.Next(); { if !attempt.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, jc.ErrorIsNil) instStatus, err := m.InstanceStatus() c.Assert(err, jc.ErrorIsNil) c.Logf("found status is %q %q", instStatus.Status, instStatus.Message) if reflect.DeepEqual(m.Addresses(), addrs) && instStatus.Message == "running" { c.Logf("machine %q address updated: %+v", m.Id(), addrs) break } c.Logf("waiting for machine %q address to be updated", m.Id()) } }
func (s *MachineSuite) testUpgradeRequest(c *gc.C, agent runner, tag string, currentTools *tools.Tools) { newVers := version.Current newVers.Patch++ newTools := envtesting.AssertUploadFakeToolsVersions(c, s.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 *toolsSuite) TestDownloadFetchesAndVerifiesSize(c *gc.C) { // Upload fake tools, then upload over the top so the SHA256 hash does not match. s.PatchValue(&version.Current.Number, testing.FakeVersionNumber) stor := s.DefaultToolsStorage envtesting.RemoveTools(c, stor, "released") tools := envtesting.AssertUploadFakeToolsVersions(c, stor, "released", "released", version.Current)[0] err := stor.Put(envtools.StorageName(tools.Version, "released"), strings.NewReader("!"), 1) c.Assert(err, jc.ErrorIsNil) resp, err := s.downloadRequest(c, tools.Version, "") c.Assert(err, jc.ErrorIsNil) s.assertErrorResponse(c, resp, http.StatusBadRequest, "error fetching tools: size mismatch for .*") s.assertToolsNotStored(c, tools.Version) }
func (s *toolsSuite) TestDownloadFetchesAndCaches(c *gc.C) { // The tools are not in binarystorage, so the download request causes // the API server to search for the tools in simplestreams, fetch // them, and then cache them in binarystorage. vers := version.MustParseBinary("1.23.0-trusty-amd64") stor := s.DefaultToolsStorage envtesting.RemoveTools(c, stor, "released") tools := envtesting.AssertUploadFakeToolsVersions(c, stor, "released", "released", vers)[0] data := s.testDownload(c, tools, "") metadata, cachedData := s.getToolsFromStorage(c, s.State, tools.Version.String()) c.Assert(metadata.Size, gc.Equals, tools.Size) c.Assert(metadata.SHA256, gc.Equals, tools.SHA256) c.Assert(string(cachedData), gc.Equals, string(data)) }
func (s *UpgradeSuite) TestUpgradeStepsStateServer(c *gc.C) { coretesting.SkipIfI386(c, "lp:1444576") coretesting.SkipIfPPC64EL(c, "lp:1444576") coretesting.SkipIfWindowsBug(c, "lp:1446885") s.setInstantRetryStrategy(c) // Upload tools to provider storage, so they can be migrated to environment storage. stor, err := environs.LegacyStorage(s.State) if !errors.IsNotSupported(err) { c.Assert(err, jc.ErrorIsNil) envtesting.AssertUploadFakeToolsVersions( c, stor, "releases", s.Environ.Config().AgentStream(), s.oldVersion) } s.assertUpgradeSteps(c, state.JobManageEnviron) s.assertStateServerUpgrades(c) }
func (s *toolsSuite) testDownload(c *gc.C, uuid string) { stor := s.Environ.Storage() envtesting.RemoveTools(c, stor) tools := envtesting.AssertUploadFakeToolsVersions(c, stor, version.Current)[0] resp, err := s.downloadRequest(c, tools.Version, uuid) c.Assert(err, gc.IsNil) defer resp.Body.Close() data, err := ioutil.ReadAll(resp.Body) c.Assert(err, gc.IsNil) c.Assert(data, gc.HasLen, int(tools.Size)) hash := sha256.New() hash.Write(data) c.Assert(fmt.Sprintf("%x", hash.Sum(nil)), gc.Equals, tools.SHA256) }
func (s *StorageSuite) TestReadList(c *gc.C) { stor, err := filestorage.NewFileStorageWriter(c.MkDir()) c.Assert(err, jc.ErrorIsNil) v100 := version.MustParseBinary("1.0.0-precise-amd64") v101 := version.MustParseBinary("1.0.1-precise-amd64") v111 := version.MustParseBinary("1.1.1-precise-amd64") v201 := version.MustParseBinary("2.0.1-precise-amd64") agentTools := envtesting.AssertUploadFakeToolsVersions(c, stor, "proposed", "proposed", v100, v101, v111, v201) t100 := agentTools[0] t101 := agentTools[1] t111 := agentTools[2] t201 := agentTools[3] for i, t := range []struct { majorVersion, minorVersion int list coretools.List }{{ -1, -1, coretools.List{t100, t101, t111, t201}, }, { 1, 0, coretools.List{t100, t101}, }, { 1, 1, coretools.List{t111}, }, { 1, -1, coretools.List{t100, t101, t111}, }, { 1, 2, nil, }, { 3, 0, nil, }} { c.Logf("test %d", i) list, err := envtools.ReadList(stor, "proposed", t.majorVersion, t.minorVersion) if t.list != nil { c.Assert(err, jc.ErrorIsNil) // ReadList doesn't set the Size or 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) } } }
func (s *localServerSuite) TestStartInstanceHardwareCharacteristics(c *gc.C) { // Ensure amd64 tools are available, to ensure an amd64 image. amd64Version := version.Current amd64Version.Arch = arch.AMD64 for _, series := range bootstrap.ToolsLtsSeries { amd64Version.Series = series envtesting.AssertUploadFakeToolsVersions(c, s.toolsMetadataStorage, amd64Version) } env := s.Prepare(c) err := bootstrap.Bootstrap(coretesting.Context(c), env, environs.BootstrapParams{}) c.Assert(err, gc.IsNil) _, hc := testing.AssertStartInstanceWithConstraints(c, env, "100", constraints.MustParse("mem=1024")) c.Check(*hc.Arch, gc.Equals, "amd64") c.Check(*hc.Mem, gc.Equals, uint64(2048)) c.Check(*hc.CpuCores, gc.Equals, uint64(1)) c.Assert(hc.CpuPower, gc.IsNil) }
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.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().String(), OldTools: currentTools.Version, NewTools: newVers, DataDir: s.DataDir(), }) }
func (s *ProvisionerSuite) TestPossibleTools(c *gc.C) { storageDir := c.MkDir() s.PatchValue(&tools.DefaultBaseURL, storageDir) stor, err := filestorage.NewFileStorageWriter(storageDir) c.Assert(err, jc.ErrorIsNil) // Set a current version that does not match the // agent-version in the environ config. currentVersion := version.MustParseBinary("1.2.3-quantal-arm64") s.PatchValue(&arch.HostArch, func() string { return currentVersion.Arch }) s.PatchValue(&series.HostSeries, func() string { return currentVersion.Series }) s.PatchValue(&version.Current, currentVersion.Number) // Upload some plausible matches, and some that should be filtered out. compatibleVersion := version.MustParseBinary("1.2.3-quantal-amd64") ignoreVersion1 := version.MustParseBinary("1.2.4-quantal-arm64") ignoreVersion2 := version.MustParseBinary("1.2.3-precise-arm64") availableVersions := []version.Binary{ currentVersion, compatibleVersion, ignoreVersion1, ignoreVersion2, } envtesting.AssertUploadFakeToolsVersions(c, stor, s.cfg.AgentStream(), s.cfg.AgentStream(), availableVersions...) // Extract the tools that we expect to actually match. expectedList, err := tools.FindTools(s.Environ, -1, -1, s.cfg.AgentStream(), coretools.Filter{ Number: currentVersion.Number, Series: currentVersion.Series, }) c.Assert(err, jc.ErrorIsNil) // Create the machine and check the tools that get passed into StartInstance. machine, err := s.BackingState.AddOneMachine(state.MachineTemplate{ Series: "quantal", Jobs: []state.MachineJob{state.JobHostUnits}, }) c.Assert(err, jc.ErrorIsNil) provisioner := s.newEnvironProvisioner(c) defer stop(c, provisioner) s.checkStartInstanceCustom( c, machine, "pork", constraints.Value{}, nil, nil, nil, nil, false, expectedList, true, ) }
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) } } }
func (s *UpgradeSuite) TestDowngradeOnMasterWhenOtherStateServerDoesntStartUpgrade(c *gc.C) { // This test checks that the master triggers a downgrade if one of // the other state server fails to signal it is ready for upgrade. // // This test is functional, ensuring that the upgrader worker // terminates the machine agent with the UpgradeReadyError which // makes the downgrade happen. // Speed up the watcher frequency to make the test much faster. s.PatchValue(&watcher.Period, 200*time.Millisecond) s.machineIsMaster = true // Signal that some state servers didn't come up for upgrade. This // should trigger a rollback to the previous agent version. s.waitForOtherStateServersErr = errors.New("boom") // Provide (fake) tools so that the upgrader has something to downgrade to. envtesting.AssertUploadFakeToolsVersions(c, s.Environ.Storage(), s.oldVersion) agent := s.createUpgradingAgent(c, state.JobManageEnviron) defer agent.Stop() var agentErr error agentDone := make(chan bool) go func() { agentErr = agent.Run(nil) close(agentDone) }() select { case <-agentDone: upgradeReadyErr, ok := agentErr.(*upgrader.UpgradeReadyError) if !ok { c.Fatalf("didn't see UpgradeReadyError, instead got: %v", agentErr) } // Confirm that the downgrade is back to the previous version. c.Assert(upgradeReadyErr.OldTools, gc.Equals, s.upgradeToVersion) c.Assert(upgradeReadyErr.NewTools, gc.Equals, s.oldVersion) case <-time.After(coretesting.LongWait): c.Fatal("machine agent did not exit as expected") } }
func (s *MachineSuite) testUpgradeRequest(c *gc.C, agent runner, tag string, currentTools *tools.Tools) { newVers := version.Binary{ Number: jujuversion.Current, Arch: arch.HostArch(), Series: series.HostSeries(), } newVers.Patch++ newTools := envtesting.AssertUploadFakeToolsVersions( c, s.DefaultToolsStorage, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), newVers)[0] err := s.State.SetModelAgentVersion(newVers.Number) c.Assert(err, jc.ErrorIsNil) err = runWithTimeout(agent) envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{ AgentName: tag, OldTools: currentTools.Version, NewTools: newTools.Version, DataDir: s.DataDir(), }) }
func (s *toolsSuite) TestDownloadFetchesAndVerifiesHash(c *gc.C) { // Upload fake tools, then upload over the top so the SHA256 hash does not match. s.PatchValue(&jujuversion.Current, testing.FakeVersionNumber) stor := s.DefaultToolsStorage envtesting.RemoveTools(c, stor, "released") current := version.Binary{ Number: jujuversion.Current, Arch: arch.HostArch(), Series: series.HostSeries(), } tools := envtesting.AssertUploadFakeToolsVersions(c, stor, "released", "released", current)[0] sameSize := strings.Repeat("!", int(tools.Size)) err := stor.Put(envtools.StorageName(tools.Version, "released"), strings.NewReader(sameSize), tools.Size) c.Assert(err, jc.ErrorIsNil) resp := s.downloadRequest(c, tools.Version, "") s.assertErrorResponse(c, resp, http.StatusBadRequest, "error fetching tools: hash mismatch for .*") s.assertToolsNotStored(c, tools.Version.String()) }
// 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, 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(inst.Id()) 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.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 *UpgraderSuite) TestUpgraderRefusesDowngradeToOrigVersionIfUpgradeNotInProgress(c *gc.C) { downgradeVersion := version.MustParseBinary("5.3.0-precise-amd64") s.confVersion = downgradeVersion.Number s.upgradeRunning = false stor := s.Environ.Storage() origTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64")) s.PatchValue(&version.Current, origTools.Version) envtesting.AssertUploadFakeToolsVersions(c, stor, downgradeVersion) err := statetesting.SetAgentVersion(s.State, downgradeVersion.Number) c.Assert(err, gc.IsNil) dummy.SetStorageDelay(coretesting.ShortWait) u := s.makeUpgrader(c) 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) }
func (s *UpgraderSuite) TestUpgraderRefusesDowngradeToOrigVersionIfUpgradeNotInProgress(c *gc.C) { downgradeVersion := version.MustParseBinary("5.3.0-precise-amd64") s.confVersion = downgradeVersion.Number s.upgradeStepsComplete.Unlock() stor := s.DefaultToolsStorage origTools := envtesting.PrimeTools(c, stor, s.DataDir(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.3-precise-amd64")) s.patchVersion(origTools.Version) envtesting.AssertUploadFakeToolsVersions( c, stor, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), downgradeVersion) err := statetesting.SetAgentVersion(s.State, downgradeVersion.Number) c.Assert(err, jc.ErrorIsNil) u := s.makeUpgrader(c) err = u.Stop() s.expectInitialUpgradeCheckDone(c) // If the upgrade would have triggered, we would have gotten an // UpgradeReadyError, since it was skipped, we get no error c.Check(err, jc.ErrorIsNil) }