Example #1
0
func (driver *MesosSchedulerDriver) AcceptOffers(offerIDs []*mesos.OfferID, operations []*mesos.Offer_Operation, filters *mesos.Filters) (mesos.Status, error) {
	driver.eventLock.Lock()
	defer driver.eventLock.Unlock()

	if stat := driver.status; stat != mesos.Status_DRIVER_RUNNING {
		return stat, fmt.Errorf("Unable to AcceptOffers, expected driver status %s, but got %s", mesos.Status_DRIVER_RUNNING, stat)
	}

	// Launch tasks
	if !driver.connected {
		log.Infoln("Ignoring AcceptOffers message, disconnected from master.")
		return driver.status, fmt.Errorf("Not connected to master.")
	}

	okOperations := make([]*mesos.Offer_Operation, 0, len(operations))

	for _, offerID := range offerIDs {
		for _, operation := range operations {
			// Keep only the slave PIDs where we run tasks so we can send
			// framework messages directly.
			if driver.cache.containsOffer(offerID) {
				// Validate
				switch *operation.Type {
				case mesos.Offer_Operation_LAUNCH:
					tasks := []*mesos.TaskInfo{}
					// Set TaskInfo.executor.framework_id, if it's missing.
					for _, task := range operation.Launch.TaskInfos {
						newTask := *task
						if newTask.Executor != nil && newTask.Executor.FrameworkId == nil {
							newTask.Executor.FrameworkId = driver.frameworkInfo.Id
						}
						tasks = append(tasks, &newTask)
					}
					for _, task := range tasks {
						if driver.cache.getOffer(offerID).offer.SlaveId.Equal(task.SlaveId) {
							// cache the tasked slave, for future communication
							pid := driver.cache.getOffer(offerID).slavePid
							driver.cache.putSlavePid(task.SlaveId, pid)
						} else {
							log.Warningf("Attempting to launch task %s with the wrong slaveId offer %s\n", task.TaskId.GetValue(), task.SlaveId.GetValue())
						}
					}
					operation.Launch.TaskInfos = tasks
					okOperations = append(okOperations, operation)
				case mesos.Offer_Operation_RESERVE:
					filtered := util.FilterResources(operation.Reserve.Resources, func(res *mesos.Resource) bool { return res.Reservation != nil })
					operation.Reserve.Resources = filtered
					okOperations = append(okOperations, operation)
				case mesos.Offer_Operation_UNRESERVE:
					filtered := util.FilterResources(operation.Unreserve.Resources, func(res *mesos.Resource) bool { return res.Reservation != nil })
					operation.Unreserve.Resources = filtered
					okOperations = append(okOperations, operation)
				case mesos.Offer_Operation_CREATE:
					filtered := util.FilterResources(operation.Create.Volumes, func(res *mesos.Resource) bool {
						return res.Reservation != nil && res.Disk != nil && res.GetName() == "disk"
					})
					operation.Create.Volumes = filtered
					okOperations = append(okOperations, operation)
				case mesos.Offer_Operation_DESTROY:
					filtered := util.FilterResources(operation.Destroy.Volumes, func(res *mesos.Resource) bool {
						return res.Reservation != nil && res.Disk != nil && res.GetName() == "disk"
					})
					operation.Destroy.Volumes = filtered
					okOperations = append(okOperations, operation)
				}
			} else {
				log.Warningf("Attempting to accept offers with unknown offer %s\n", offerID.GetValue())
			}
		}

		driver.cache.removeOffer(offerID) // if offer
	}

	// Accept Offers
	accept := &mesos.Call_Accept{
		OfferIds:   offerIDs,
		Operations: okOperations,
		Filters:    filters,
	}
	callType := mesos.Call_ACCEPT
	message := &mesos.Call{
		FrameworkId: driver.frameworkInfo.Id,
		Type:        &callType,
		Accept:      accept,
	}

	if err := driver.send(driver.masterPid, message); err != nil {
		for _, operation := range operations {
			if *operation.Type == mesos.Offer_Operation_LAUNCH {
				for _, task := range operation.Launch.TaskInfos {
					driver.pushLostTask(task, "Unable to launch tasks: "+err.Error())
				}
			}
		}
		log.Errorf("Failed to send LaunchTask message: %v\n", err)
		return driver.status, err
	}

	return driver.status, nil
}
Example #2
0
func (sched *ExampleScheduler) ResourceOffers(driver sched.SchedulerDriver, offers []*mesos.Offer) {

	if sched.tasksLaunched >= sched.totalTasks {
		log.Info("decline all of the offers since all of our tasks are already launched")
		ids := make([]*mesos.OfferID, len(offers))
		for i, offer := range offers {
			ids[i] = offer.Id
		}
		driver.LaunchTasks(ids, []*mesos.TaskInfo{}, &mesos.Filters{RefuseSeconds: proto.Float64(120)})
		return
	}
	for _, offer := range offers {
		cpuResources := util.FilterResources(offer.Resources, func(res *mesos.Resource) bool {
			return res.GetName() == "cpus"
		})
		cpus := 0.0
		for _, res := range cpuResources {
			cpus += res.GetScalar().GetValue()
		}

		memResources := util.FilterResources(offer.Resources, func(res *mesos.Resource) bool {
			return res.GetName() == "mem"
		})
		mems := 0.0
		for _, res := range memResources {
			mems += res.GetScalar().GetValue()
		}

		log.Infoln("Received Offer <", offer.Id.GetValue(), "> with cpus=", cpus, " mem=", mems)

		remainingCpus := cpus
		remainingMems := mems

		var tasks []*mesos.TaskInfo
		for sched.tasksLaunched < sched.totalTasks &&
			CPUS_PER_TASK <= remainingCpus &&
			MEM_PER_TASK <= remainingMems {

			sched.tasksLaunched++

			taskId := &mesos.TaskID{
				Value: proto.String(strconv.Itoa(sched.tasksLaunched)),
			}

			task := &mesos.TaskInfo{
				Name:     proto.String("go-task-" + taskId.GetValue()),
				TaskId:   taskId,
				SlaveId:  offer.SlaveId,
				Executor: sched.executor,
				Resources: []*mesos.Resource{
					util.NewScalarResource("cpus", CPUS_PER_TASK),
					util.NewScalarResource("mem", MEM_PER_TASK),
				},
			}
			log.Infof("Prepared task: %s with offer %s for launch\n", task.GetName(), offer.Id.GetValue())

			tasks = append(tasks, task)
			remainingCpus -= CPUS_PER_TASK
			remainingMems -= MEM_PER_TASK
		}
		log.Infoln("Launching ", len(tasks), "tasks for offer", offer.Id.GetValue())
		driver.LaunchTasks([]*mesos.OfferID{offer.Id}, tasks, &mesos.Filters{RefuseSeconds: proto.Float64(5)})
	}
}