Ejemplo n.º 1
0
// StartBackgroundActions spawns goroutines that monitor various parts of the
// execution - heartbeats, timeouts, logging, etc.
func (agt *Agent) StartBackgroundActions(signalHandler TerminateHandler) chan FinalTaskFunc {
	completed := make(chan FinalTaskFunc)
	agt.heartbeater.StartHeartbeating()
	agt.statsCollector.LogStats(agt.taskConfig.Expansions)
	agt.timeoutWatcher.NotifyTimeouts(agt.signalChan)
	go signalHandler.HandleSignals(agt, completed)

	// listen for SIGQUIT and dump a stack trace to system logs if received.
	go util.DumpStackOnSIGQUIT(evergreen.NewInfoLoggingWriter(agt.logger.System))
	return completed
}
Ejemplo n.º 2
0
func (sc *StatsCollector) LogStats(exp *command.Expansions) {
	sc.expandCommands(exp)

	if sc.Interval < 0 {
		panic(fmt.Sprintf("Illegal interval: %v", sc.Interval))
	}
	if sc.stop != nil {
		panic("StatsCollector goroutine already running!")
	}
	if sc.Interval == 0 {
		sc.Interval = 60 * time.Second
	}

	sysloggerInfoWriter := evergreen.NewInfoLoggingWriter(sc.logger)
	sysloggerErrWriter := evergreen.NewErrorLoggingWriter(sc.logger)
	sc.stop = make(chan bool)

	go func() {
		ticker := time.NewTicker(sc.Interval)
		for {
			select {
			case <-ticker.C:
				for _, cmd := range sc.Cmds {
					sc.logger.Logf(slogger.INFO, "Running %v", cmd)
					command := &command.LocalCommand{
						CmdString: cmd,
						Stdout:    sysloggerInfoWriter,
						Stderr:    sysloggerErrWriter,
					}
					if err := command.Run(); err != nil {
						sc.logger.Logf(slogger.ERROR, "error running '%v': %v", cmd, err)
					}
				}
			case <-sc.stop:
				sc.logger.Logf(slogger.INFO, "StatsCollector ticker stopping.")
				ticker.Stop()
				sc.stop = nil
				return
			}
		}
	}()
}
Ejemplo n.º 3
0
// constructPwdUpdateCommand returns a RemoteCommand struct used to
// set the RDP password on a remote windows machine.
func constructPwdUpdateCommand(settings *evergreen.Settings, hostObj *host.Host,
	password string) (*command.RemoteCommand, error) {

	cloudHost, err := providers.GetCloudHost(hostObj, settings)
	if err != nil {
		return nil, err
	}

	hostInfo, err := util.ParseSSHInfo(hostObj.Host)
	if err != nil {
		return nil, err
	}

	sshOptions, err := cloudHost.GetSSHOptions()
	if err != nil {
		return nil, err
	}

	outputLineHandler := evergreen.NewInfoLoggingWriter(&evergreen.Logger)
	errorLineHandler := evergreen.NewErrorLoggingWriter(&evergreen.Logger)

	updatePwdCmd := fmt.Sprintf("net user %v %v && sc config "+
		"sshd obj= '.\\%v' password= \"%v\"", hostObj.User, password,
		hostObj.User, password)

	// construct the required termination command
	remoteCommand := &command.RemoteCommand{
		CmdString:       updatePwdCmd,
		Stdout:          outputLineHandler,
		Stderr:          errorLineHandler,
		LoggingDisabled: true,
		RemoteHostName:  hostInfo.Hostname,
		User:            hostObj.User,
		Options:         append([]string{"-p", hostInfo.Port}, sshOptions...),
		Background:      false,
	}
	return remoteCommand, nil
}
Ejemplo n.º 4
0
func (sc *StatsCollector) LogStats(exp *command.Expansions) {
	sc.expandCommands(exp)

	if sc.Interval < 0 {
		panic(fmt.Sprintf("Illegal interval: %v", sc.Interval))
	}
	if sc.Interval == 0 {
		sc.Interval = 60 * time.Second
	}

	sysloggerInfoWriter := evergreen.NewInfoLoggingWriter(sc.logger)
	sysloggerErrWriter := evergreen.NewErrorLoggingWriter(sc.logger)

	go func() {
		for {
			select {
			case <-sc.stop:
				sc.logger.Logf(slogger.INFO, "StatsCollector ticker stopping.")
				return
			default:
				for _, cmd := range sc.Cmds {
					sc.logger.Logf(slogger.INFO, "Running %v", cmd)
					command := &command.LocalCommand{
						CmdString: cmd,
						Stdout:    sysloggerInfoWriter,
						Stderr:    sysloggerErrWriter,
					}
					if err := command.Run(); err != nil {
						sc.logger.Logf(slogger.ERROR, "error running '%v': %v", cmd, err)
					}
				}
				time.Sleep(sc.Interval)
			}
		}
	}()
}
Ejemplo n.º 5
0
// MakePatchedConfig takes in the path to a remote configuration a stringified version
// of the current project and returns an unmarshalled version of the project
// with the patch applied
func MakePatchedConfig(p *patch.Patch, remoteConfigPath, projectConfig string) (
	*Project, error) {
	for _, patchPart := range p.Patches {
		// we only need to patch the main project and not any other modules
		if patchPart.ModuleName != "" {
			continue
		}
		// write patch file
		patchFilePath, err := util.WriteToTempFile(patchPart.PatchSet.Patch)
		if err != nil {
			return nil, fmt.Errorf("could not write patch file: %v", err)
		}
		defer os.Remove(patchFilePath)
		// write project configuration
		configFilePath, err := util.WriteToTempFile(projectConfig)
		if err != nil {
			return nil, fmt.Errorf("could not write config file: %v", err)
		}
		defer os.Remove(configFilePath)

		// clean the working directory
		workingDirectory := filepath.Dir(patchFilePath)
		localConfigPath := filepath.Join(
			workingDirectory,
			remoteConfigPath,
		)
		parentDir := strings.Split(
			remoteConfigPath,
			string(os.PathSeparator),
		)[0]
		err = os.RemoveAll(filepath.Join(workingDirectory, parentDir))
		if err != nil {
			return nil, err
		}
		if err = os.MkdirAll(filepath.Dir(localConfigPath), 0755); err != nil {
			return nil, err
		}
		// rename the temporary config file name to the remote config
		// file path if we are patching an existing remote config
		if len(projectConfig) > 0 {
			if err = os.Rename(configFilePath, localConfigPath); err != nil {
				return nil, fmt.Errorf("could not rename file '%v' to '%v': %v",
					configFilePath, localConfigPath, err)
			}
			defer os.Remove(localConfigPath)
		}

		// selectively apply the patch to the config file
		patchCommandStrings := []string{
			fmt.Sprintf("set -o verbose"),
			fmt.Sprintf("set -o errexit"),
			fmt.Sprintf("git apply --whitespace=fix --include=%v < '%v'",
				remoteConfigPath, patchFilePath),
		}

		patchCmd := &command.LocalCommand{
			CmdString:        strings.Join(patchCommandStrings, "\n"),
			WorkingDirectory: workingDirectory,
			Stdout:           evergreen.NewInfoLoggingWriter(&evergreen.Logger),
			Stderr:           evergreen.NewErrorLoggingWriter(&evergreen.Logger),
			ScriptMode:       true,
		}

		if err = patchCmd.Run(); err != nil {
			return nil, fmt.Errorf("could not run patch command: %v", err)
		}
		// read in the patched config file
		data, err := ioutil.ReadFile(localConfigPath)
		if err != nil {
			return nil, fmt.Errorf("could not read patched config file: %v",
				err)
		}
		project := &Project{}
		if err = LoadProjectInto(data, p.Project, project); err != nil {
			return nil, err
		}
		return project, nil
	}
	return nil, fmt.Errorf("no patch on project")
}
Ejemplo n.º 6
0
func dumpToLogs(task, command string, stack []byte, agt *Agent) {
	if agt != nil && agt.logger != nil {
		logWriter := evergreen.NewInfoLoggingWriter(agt.logger.System)
		dumpDebugInfo(task, command, stack, logWriter)
	}
}