Example #1
0
// WatchForFinishedTestRuns simply watches the local cache for any test runs that have test data.
// It will periodically look at the table and send any present test data back to the server as a response.
// When the server has successfully received this data, it will send a task back to this specific agent
// to delete this row from the cache.
func WatchForFinishedTestRuns(cfg config.Config) {

	var ac = cache.NewAgentCache(cfg)

	agentUuid := ac.GetKeyValue("uuid")

	for {

		time.Sleep(5000 * time.Millisecond)

		testruns, err := ac.GetFinishedTestRuns()
		if err != nil {
			log.Error("Problem retrieving finished test runs")
			os.Exit(1)
		}

		for testUuid, testData := range testruns {

			log.Debug("Found ripe testrun: ", testUuid)

			var utdr = responses.UploadTestDataResponse{
				TestUuid: testUuid,
				TestData: testData,
			}
			utdr.AgentUuid = agentUuid
			utdr.Type = "TestData" //TODO(mierdin): This is an extra step. Maybe a factory function for the task could help here?

			var tc = comms.NewToDDComms(cfg)
			tc.CommsPackage.SendResponse(utdr)

		}

	}

}
Example #2
0
File: main.go Project: twm1010/todd
func main() {

	todd_version := "0.0.1"

	cfg := config.GetConfig(arg_config)

	// Start serving collectors and testlets, and retrieve map of names and hashes
	assets := serveAssets(cfg)

	// Perform database initialization tasks
	tdb, err := db.NewToddDB(cfg)
	if err != nil {
		log.Fatalf("Error setting up database: %v\n", err)
	}

	if err := tdb.Init(); err != nil {
		log.Fatalf("Error initializing database: %v\n", err)
	}

	// Initialize API
	var tapi toddapi.ToDDApi
	go func() {
		log.Fatal(tapi.Start(cfg))
	}()

	// Start listening for agent advertisements
	var tc = comms.NewToDDComms(cfg)
	go tc.CommsPackage.ListenForAgent(assets)

	// Kick off group calculation in background
	go func() {
		for {
			log.Info("Beginning group calculation")
			grouping.CalculateGroups(cfg)
			time.Sleep(time.Second * time.Duration(cfg.Grouping.Interval))
		}
	}()

	log.Infof("ToDD server v%s. Press any key to exit...\n", todd_version)

	// Sssh, sssh, only dreams now....
	for {
		time.Sleep(time.Second * 10)
	}
}
Example #3
0
// CalculateGroups is a function designed to ingest a list of group objects, a collection of agents, and
// return a map that contains the resulting group for each agent UUID.
func CalculateGroups(cfg config.Config) {

	tdb, err := db.NewToddDB(cfg)
	if err != nil {
		log.Fatalf("Error connecting to DB: %v", err)
	}

	// Retrieve all currently active agents
	agents, err := tdb.GetAgents()
	if err != nil {
		log.Fatalf("Error retrieving agents: %v", err)
	}

	// Retrieve all objects with type "group"
	group_objs, err := tdb.GetObjects("group")
	if err != nil {
		log.Fatalf("Error retrieving groups: %v", err)
	}

	// Cast retrieved slice of ToddObject interfaces to actual GroupObjects
	groups := make([]objects.GroupObject, len(group_objs))
	for i, gobj := range group_objs {
		groups[i] = gobj.(objects.GroupObject)
	}

	// groupmap contains the uuid-to-groupname mappings to be used for test runs
	groupmap := map[string]string{}

	// This slice will hold all of the agents that are sad because they didn't get into a group
	var lonelyAgents []defs.AgentAdvert

next:
	for x := range agents {

		for i := range groups {

			// See if this agent is in this group
			if isInGroup(groups[i].Spec.Matches, agents[x].Facts) {

				// Insert this group name ("Label") into groupmap under the key of the UUID for the agent that belongs to it
				log.Debugf("Agent %s is in group %s\n", agents[x].Uuid, groups[i].Label)
				groupmap[agents[x].Uuid] = groups[i].Label
				continue next

			}
		}

		// The "continue next" should prohibit all agents that have a group from getting to this point,
		// so the only ones left do not have a group.
		lonelyAgents = append(lonelyAgents, agents[x])

	}

	// Write results to database
	err = tdb.SetGroupMap(groupmap)
	if err != nil {
		log.Fatalf("Error setting group map: %v", err)
	}

	// Send notifications to each agent to let them know what group they're in, so they can cache it
	var tc = comms.NewToDDComms(cfg)
	for uuid, groupName := range groupmap {
		setGroupTask := tasks.SetGroupTask{
			GroupName: groupName,
		}

		setGroupTask.Type = "SetGroup" //TODO(mierdin): Apparently this is necessary because inner type promotion doesn't apply for struct literals?
		tc.CommsPackage.SendTask(uuid, setGroupTask)
	}

	// need to send a message to all agents that weren't in groupmap to set their group to nothing
	for x := range lonelyAgents {
		setGroupTask := tasks.SetGroupTask{
			GroupName: "",
		}

		setGroupTask.Type = "SetGroup" //TODO(mierdin): Apparently this is necessary because inner type promotion doesn't apply for struct literals?
		tc.CommsPackage.SendTask(lonelyAgents[x].Uuid, setGroupTask)
	}
}
Example #4
0
File: main.go Project: twm1010/todd
func main() {

	cfg := config.GetConfig(arg_config)

	// Set up cache
	var ac = cache.NewAgentCache(cfg)
	ac.Init()

	// Generate UUID
	uuid := hostresources.GenerateUuid()
	ac.SetKeyValue("uuid", uuid)

	log.Infof("ToDD Agent Activated: %s", uuid)

	// Start test data reporting service
	go testing.WatchForFinishedTestRuns(cfg)

	// Construct comms package
	var tc = comms.NewToDDComms(cfg)

	// Spawn goroutine to listen for tasks issued by server
	go func() {
		for {
			err := tc.CommsPackage.ListenForTasks(uuid)
			if err != nil {
				log.Warn("ListenForTasks reported a failure. Trying again...")
			}
		}
	}()

	// Watch for changes to group membership
	go tc.CommsPackage.WatchForGroup()

	// Continually advertise agent status into message queue
	for {

		// Gather assets here as a map, and refer to a key in that map in the below struct
		gatheredAssets := GetLocalAssets(cfg)

		var defaultaddr string
		if cfg.LocalResources.IPAddrOverride != "" {
			defaultaddr = cfg.LocalResources.IPAddrOverride
		} else {
			defaultaddr = hostresources.GetIPOfInt(cfg.LocalResources.DefaultInterface).String()
		}

		// Create an AgentAdvert instance to represent this particular agent
		me := defs.AgentAdvert{
			Uuid:           uuid,
			DefaultAddr:    defaultaddr,
			FactCollectors: gatheredAssets["factcollectors"],
			Testlets:       gatheredAssets["testlets"],
			Facts:          facts.GetFacts(cfg),
			LocalTime:      time.Now().UTC(),
		}

		// Advertise this agent
		err := tc.CommsPackage.AdvertiseAgent(me)
		if err != nil {
			log.Error("Failed to advertise agent after several retries")
		}

		time.Sleep(15 * time.Second) // TODO(moswalt): make configurable
	}

}