Exemple #1
0
// WildcardMapper maps k8s wildcard ports (hostPort == 0) to any available offer port
func WildcardMapper(pod *api.Pod, roles []string, offer *mesos.Offer) ([]Mapping, error) {
	mapping, err := FixedMapper(pod, roles, offer)
	if err != nil {
		return nil, err
	}

	taken := make(map[uint64]struct{})
	for _, entry := range mapping {
		taken[entry.OfferPort] = struct{}{}
	}

	wildports := []Mapping{}
	for i, container := range pod.Spec.Containers {
		for pi, port := range container.Ports {
			if port.HostPort == 0 {
				wildports = append(wildports, Mapping{
					ContainerIdx: i,
					PortIdx:      pi,
				})
			}
		}
	}

	remaining := len(wildports)
	resources.ForeachPortsRange(offer.GetResources(), roles, func(bp, ep uint64, role string) {
		log.V(3).Infof("Searching for wildcard port in range {%d:%d}", bp, ep)
		for i := range wildports {
			if wildports[i].OfferPort != 0 {
				continue
			}
			for port := bp; port <= ep && remaining > 0; port++ {
				if _, inuse := taken[port]; inuse {
					continue
				}
				wildports[i].OfferPort = port
				wildports[i].Role = resources.CanonicalRole(role)
				mapping = append(mapping, wildports[i])
				remaining--
				taken[port] = struct{}{}
				break
			}
		}
	})

	if remaining > 0 {
		err := &PortAllocationError{
			PodID: pod.Namespace + "/" + pod.Name,
		}
		// it doesn't make sense to include a port list here because they were all zero (wildcards)
		return nil, err
	}

	return mapping, nil
}
Exemple #2
0
// FixedMapper maps k8s host ports to offered ports ignoring hostPorts == 0 (remaining pod-private)
func FixedMapper(pod *api.Pod, roles []string, offer *mesos.Offer) ([]Mapping, error) {
	requiredPorts := make(map[uint64]Mapping)
	mapping := []Mapping{}
	for i, container := range pod.Spec.Containers {
		// strip all port==0 from this array; k8s already knows what to do with zero-
		// ports (it does not create 'port bindings' on the minion-host); we need to
		// remove the wildcards from this array since they don't consume host resources
		for pi, port := range container.Ports {
			if port.HostPort == 0 {
				continue // ignore
			}
			m := Mapping{
				ContainerIdx: i,
				PortIdx:      pi,
				OfferPort:    uint64(port.HostPort),
			}
			if entry, inuse := requiredPorts[uint64(port.HostPort)]; inuse {
				return nil, &DuplicateError{entry, m}
			}
			requiredPorts[uint64(port.HostPort)] = m
		}
	}

	resources.ForeachPortsRange(offer.GetResources(), roles, func(bp, ep uint64, role string) {
		for port := range requiredPorts {
			log.V(3).Infof("evaluating port range {%d:%d} %d", bp, ep, port)
			if (bp <= port) && (port <= ep) {
				m := requiredPorts[port]
				m.Role = resources.CanonicalRole(role)
				mapping = append(mapping, m)
				delete(requiredPorts, port)
			}
		}
	})

	unsatisfiedPorts := len(requiredPorts)
	if unsatisfiedPorts > 0 {
		err := &PortAllocationError{
			PodID: pod.Namespace + "/" + pod.Name,
		}
		for p := range requiredPorts {
			err.Ports = append(err.Ports, p)
		}
		return nil, err
	}

	return mapping, nil
}