Exemple #1
0
// NewDefaultProcurement returns the default procurement strategy that combines validation
// and responsible Mesos resource procurement. c and m are resource quantities written into
// k8s api.Pod.Spec's that don't declare resources (all containers in k8s-mesos require cpu
// and memory limits).
func NewDefaultProcurement(prototype *mesos.ExecutorInfo, eir executorinfo.Registry) Procurement {
	return AllOrNothingProcurement([]Procurement{
		NewNodeProcurement(),
		NewPodResourcesProcurement(),
		NewPortsProcurement(),
		NewExecutorResourceProcurer(prototype.GetResources(), eir),
	})
}
Exemple #2
0
// initializeStaticPodsSource unzips the data slice into the static-pods directory
func (k *Executor) initializeStaticPodsSource(executorInfo *mesos.ExecutorInfo) {
	if data := executorInfo.GetData(); len(data) > 0 && k.staticPodsConfigPath != "" {
		log.V(2).Infof("extracting static pods config to %s", k.staticPodsConfigPath)
		err := podutil.WriteToDir(
			k.staticPodsFilters.Do(podutil.Gunzip(executorInfo.Data)),
			k.staticPodsConfigPath,
		)
		if err != nil {
			log.Errorf("failed to initialize static pod configuration: %v", err)
		}
	}
}
Exemple #3
0
// compute a hashcode for ExecutorInfo that may be used as a reasonable litmus test
// with respect to compatibility across HA schedulers. the intent is that an HA scheduler
// should fail-fast if it doesn't pass this test, rather than generating (potentially many)
// errors at run-time because a Mesos master decides that the ExecutorInfo generated by a
// secondary scheduler doesn't match that of the primary scheduler.
//
// Note: We intentionally leave out the Resources in this hash because they are
//       set during procurement and should not lead to a different ExecutorId.
//       This also means that the Resources do not contribute to offer
//       compatibility checking. But as we persist and restore the Resources
//       through node anotation we make sure that the right resources are chosen
//       during task launch.
//
// see https://github.com/apache/mesos/blob/0.22.0/src/common/type_utils.cpp#L110
func hash(info *mesos.ExecutorInfo) uint64 {
	// !!! we specifically do NOT include:
	// - Framework ID because it's a value that's initialized too late for us to use
	// - Executor ID because it's a value that includes a copy of this hash
	buf := &bytes.Buffer{}
	buf.WriteString(info.GetName())
	buf.WriteString(info.GetSource())
	buf.Write(info.Data)

	if info.Command != nil {
		buf.WriteString(info.Command.GetValue())
		buf.WriteString(info.Command.GetUser())
		buf.WriteString(strconv.FormatBool(info.Command.GetShell()))
		if sz := len(info.Command.Arguments); sz > 0 {
			x := make([]string, sz)
			copy(x, info.Command.Arguments)
			sort.Strings(x)
			for _, item := range x {
				buf.WriteString(item)
			}
		}
		if vars := info.Command.Environment.GetVariables(); len(vars) > 0 {
			names := []string{}
			e := make(map[string]string)

			for _, v := range vars {
				if name := v.GetName(); name != "" {
					names = append(names, name)
					e[name] = v.GetValue()
				}
			}
			sort.Strings(names)
			for _, n := range names {
				buf.WriteString(n)
				buf.WriteString("=")
				buf.WriteString(e[n])
			}
		}
		if uris := info.Command.GetUris(); len(uris) > 0 {
			su := []string{}
			for _, uri := range uris {
				su = append(su, fmt.Sprintf("%s%t%t", uri.GetValue(), uri.GetExecutable(), uri.GetExtract()))
			}
			sort.Strings(su)
			for _, uri := range su {
				buf.WriteString(uri)
			}
		}
		//TODO(jdef) add support for Container
	}
	table := crc64.MakeTable(crc64.ECMA)
	return crc64.Checksum(buf.Bytes(), table)
}
func annotationsFor(ei *mesos.ExecutorInfo) (annotations map[string]string, err error) {
	annotations = map[string]string{}
	if ei == nil {
		return
	}

	var buf bytes.Buffer
	if err = executorinfo.EncodeResources(&buf, ei.GetResources()); err != nil {
		return
	}

	annotations[meta.ExecutorIdKey] = ei.GetExecutorId().GetValue()
	annotations[meta.ExecutorResourcesKey] = buf.String()

	return
}
Exemple #5
0
func nodeInfo(si *mesos.SlaveInfo, ei *mesos.ExecutorInfo) NodeInfo {
	var executorCPU, executorMem float64

	// get executor resources
	if ei != nil {
		for _, r := range ei.GetResources() {
			if r == nil || r.GetType() != mesos.Value_SCALAR {
				continue
			}
			switch r.GetName() {
			case "cpus":
				executorCPU += r.GetScalar().GetValue()
			case "mem":
				executorMem += r.GetScalar().GetValue()
			}
		}
	}

	// get resource capacity of the node
	ni := NodeInfo{}
	for _, r := range si.GetResources() {
		if r == nil || r.GetType() != mesos.Value_SCALAR {
			continue
		}

		switch r.GetName() {
		case "cpus":
			// We intentionally take the floor of executorCPU because cores are integers
			// and we would loose a complete cpu here if the value is <1.
			// TODO(sttts): switch to float64 when "Machine Allocables" are implemented
			ni.Cores += int(r.GetScalar().GetValue())
		case "mem":
			ni.Mem += int64(r.GetScalar().GetValue()) * 1024 * 1024
		}
	}

	// TODO(sttts): subtract executorCPU/Mem from static pod resources before subtracting them from the capacity
	ni.Cores -= int(executorCPU)
	ni.Mem -= int64(executorMem) * 1024 * 1024

	return ni
}
func setCommandArgument(ei *mesos.ExecutorInfo, flag, value string, create bool) {
	argv := []string{}
	overwrite := false
	if ei.Command != nil && ei.Command.Arguments != nil {
		argv = ei.Command.Arguments
		for i, arg := range argv {
			if strings.HasPrefix(arg, flag+"=") {
				overwrite = true
				argv[i] = flag + "=" + value
				break
			}
		}
	}
	if !overwrite && create {
		argv = append(argv, flag+"="+value)
		if ei.Command == nil {
			ei.Command = &mesos.CommandInfo{}
		}
		ei.Command.Arguments = argv
	}
}