func (a *Agent) HandleEventJobOffered(event registry.Event) { jo := event.Payload.(job.JobOffer) log.V(1).Infof("EventJobOffered(%s): verifying ability to run Job", jo.Job.Name) a.state.Lock() defer a.state.Unlock() // Everything we check against could change over time, so we track all // offers starting here for future bidding even if we can't bid now a.state.TrackOffer(jo) a.state.TrackJobPeers(jo.Job.Name, jo.Job.Payload.Peers) metadata := extractMachineMetadata(jo.Job.Payload.Requirements) if !a.Machine.HasMetadata(metadata) { log.V(1).Infof("EventJobOffered(%s): local Machine Metadata insufficient", jo.Job.Name) return } if a.hasConflict(&jo.Job) { log.V(1).Infof("EventJobOffered(%s): local Job conflict, ignoring offer", jo.Job.Name) return } if !a.hasAllLocalPeers(&jo.Job) { log.V(1).Infof("EventJobOffered(%s): necessary peer Jobs are not running locally", jo.Job.Name) return } log.Infof("EventJobOffered(%s): passed all criteria, submitting JobBid", jo.Job.Name) jb := job.NewBid(jo.Job.Name, a.Machine.BootId) a.Registry.SubmitJobBid(jb) a.state.TrackBid(jo.Job.Name) }
// Only call this from a locked AgentState context func (a *Agent) bidForPossibleOffers() { for _, offer := range a.state.GetUnbadeOffers() { if !a.hasConflict(&offer.Job) && a.hasAllLocalPeers(&offer.Job) { log.Infof("Unscheduled Job(%s) has no local conflicts, submitting JobBid", offer.Job.Name) jb := job.NewBid(offer.Job.Name, a.Machine.BootId) a.Registry.SubmitJobBid(jb) a.state.TrackBid(jb.JobName) } } }
func (a *Agent) HandleEventJobScheduled(event registry.Event) { jobName := event.Payload.(string) a.state.Lock() defer a.state.Unlock() a.state.DropOffer(jobName) a.state.DropBid(jobName) if event.Context.BootId != a.Machine.BootId { log.V(1).Infof("EventJobScheduled(%s): Job not scheduled to this Agent", jobName) a.bidForPossibleOffers() return } else { log.V(1).Infof("EventJobScheduled(%s): Job scheduled to this Agent", jobName) } log.V(1).Infof("EventJobScheduled(%s): Fetching Job from Registry", jobName) j := a.Registry.GetJob(jobName) if j == nil { log.V(1).Infof("EventJobScheduled(%s): Job not found in Registry") return } // Reassert there are no conflicts if a.hasConflict(j) { log.V(1).Infof("EventJobScheduled(%s): Local conflict found, cancelling Job", jobName) a.Registry.CancelJob(jobName) return } log.Infof("EventJobScheduled(%s): Starting Job", j.Name) a.Manager.StartJob(j) reversePeers := a.state.GetJobsByPeer(jobName) for _, peer := range reversePeers { log.V(1).Infof("EventJobScheduled(%s): Found unresolved offer for Peer(%s)", jobName, peer) if peerJob := a.Registry.GetJob(peer); !a.hasConflict(peerJob) { log.Infof("EventJobScheduled(%s): Submitting JobBid for Peer(%s)", jobName, peer) jb := job.NewBid(peer, a.Machine.BootId) a.Registry.SubmitJobBid(jb) a.state.TrackBid(jb.JobName) } else { log.V(1).Infof("EventJobScheduled(%s): Would submit JobBid for Peer(%s), but local conflict exists", jobName, peer) } } }
func filterEventJobBidSubmitted(resp *etcd.Response) *Event { if resp.Action != "set" { return nil } dir, machName := path.Split(resp.Node.Key) dir, prefix := path.Split(strings.TrimSuffix(dir, "/")) if prefix != "bids" { return nil } dir, jobName := path.Split(strings.TrimSuffix(dir, "/")) prefix = path.Base(strings.TrimSuffix(dir, "/")) if prefix != offerPrefix { return nil } jb := job.NewBid(jobName, machName) return &Event{"EventJobBidSubmitted", *jb, nil} }