示例#1
0
func (e *RegisterSupervisorExecutor) Execute(t *Task) error {
	if e.arg.Host == "" {
		return errors.New("Please specify a host to register")
	}
	// check health of to be registered supervisor
	health, err := supervisor.HealthCheck(e.arg.Host)
	if err != nil {
		e.reply.Status = StatusError
		return err
	}
	if health.Status != StatusOk && health.Status != StatusFull {
		e.reply.Status = health.Status
		return errors.New("Status is " + health.Status)
	}
	if health.Region != Region {
		e.reply.Status = "Region Mismatch"
		return errors.New("Supervisor Region (" + health.Region + ") does not match Manager Region (" + Region + ")")
	}
	err = datamodel.Supervisor(e.arg.Host).Touch()
	if err != nil {
		e.reply.Status = StatusError
		return err
	}
	// try to push all ip groups to this new supervisor
	if err := netsec.UpdateSupervisor(e.arg.Host); err != nil {
		return err
	}
	if err == nil {
		e.reply.Status = StatusOk
	} else {
		e.reply.Status = StatusError
	}
	return err
}
func deployToZone(respCh chan *DeployZoneResult, deps map[string]DepsType, rawManifest *Manifest, sha,
	env string, hosts []string, zone string) {
	hostNum := 0
	failures := 0
	deployed := uint(0)
	maxFailures := len(hosts)
	deployedContainers := []*Container{}
	for deployed < rawManifest.Instances && failures < maxFailures {
		numToDeploy := rawManifest.Instances - deployed
		respCh := make(chan *DeployHostResult, numToDeploy)
		for i := uint(0); i < numToDeploy; i++ {
			host := hosts[hostNum]
			// check health on host to figure out its zone to get the deps
			ihReply, err := supervisor.HealthCheck(host)
			if err == nil && ihReply.Status == StatusOk {
				// only try to deploy if health was fine
				// duplicate manifest and get deps
				manifest := rawManifest.Dup()
				manifest.Deps = deps[ihReply.Zone]
				go deployToHost(respCh, manifest, sha, env, host)
			}
			hostNum++
			if hostNum >= len(hosts) {
				hostNum = 0
			}
		}
		numResult := uint(0)
		for result := range respCh {
			if result.Error != nil {
				failures++
			} else {
				deployed++
				deployedContainers = append(deployedContainers, result.Container)
			}
			numResult++
			if numResult >= numToDeploy { // we're done
				close(respCh)
			}
		}
	}
	if failures >= maxFailures {
		respCh <- &DeployZoneResult{
			Zone:       zone,
			Containers: deployedContainers,
			Error: errors.New(fmt.Sprintf("Failed to deploy %d instances in zone %s.", rawManifest.Instances,
				zone)),
		}
		return
	}
	respCh <- &DeployZoneResult{
		Zone:       zone,
		Containers: deployedContainers,
		Error:      nil,
	}
	return
}
示例#3
0
func ChooseSupervisorsList(app, sha, env string, cpu, memory uint, zones []string,
	excludeSupervisors map[string]bool) (SupervisorAndWeightList, error) {
	hosts, err := ListSupervisorsForApp(app)
	if err != nil {
		log.Println("Error listing hosts for app "+app+":", err)
		return nil, err
	}
	if len(hosts) == 0 {
		return nil, errors.New("No hosts available for app " + app)
	}
	list := SupervisorAndWeightList{}
	for _, host := range hosts {
		if excludeSupervisors != nil && excludeSupervisors[host] {
			continue
		}
		// check if this host already has this app-sha
		hostInfo, err := Supervisor(host).Info()
		if err != nil {
			continue // bad host, skip.
		}
		health, err := supervisor.HealthCheck(host)
		if err != nil || health.Status != StatusOk {
			continue // health check fail
		}
		if health.Containers.Free == 0 || health.Memory.Free < memory || health.CPUShares.Free < cpu {
			continue
		}
		// figure out how many we can stack on
		free := health.Containers.Free
		if health.Memory.Free/memory < free {
			free = health.Memory.Free / memory
		}
		if health.CPUShares.Free/cpu < free {
			free = health.CPUShares.Free / cpu
		}
		// we're chillin. add the weight to the host map
		// +2 weight for every one of this app/sha/env we see
		weight := float64(2*hostInfo.CountAppShaEnv(app, sha, env)) +
			(float64(health.Memory.Used+memory) / float64(health.Memory.Total)) +
			(float64(health.CPUShares.Used+cpu) / float64(health.CPUShares.Total))
		list = append(list, SupervisorAndWeight{Supervisor: host, Zone: health.Zone, Free: free, Weight: weight})
	}
	sort.Sort(list) // sort in weight order, lowest to highest
	return list, nil
}
示例#4
0
func GetUsage() (map[string]*SupervisorUsage, error) {
	// for each supervisor
	//   get health check to figure out total CPUShares, Memory, Price
	//   get list of containers
	//   fill in data in SupervisorUsage
	supers, err := datamodel.ListSupervisors()
	if err != nil {
		return nil, err
	}
	usageMap := map[string]*SupervisorUsage{}
	for _, super := range supers {
		usage := &SupervisorUsage{Containers: map[string]*ContainerUsage{}}
		hreply, err := supervisor.HealthCheck(super)
		if err != nil {
			return nil, err
		}
		usage.Host = super
		price := hreply.Price
		total_cpu := hreply.CPUShares.Total
		total_mem := hreply.Memory.Total
		usage.TotalPrice = price
		usage.TotalContainers = hreply.Containers.Total
		usage.TotalCPUShares = total_cpu
		usage.TotalMemory = total_mem
		lreply, err := supervisor.List(super)
		if err != nil {
			return nil, err
		}
		var conts uint = 0
		var cpu uint = 0
		var mem uint = 0
		var cpu_price float64 = 0.0
		var mem_price float64 = 0.0
		for id, cont := range lreply.Containers {
			conts += 1
			cpu += cont.Manifest.CPUShares
			mem += cont.Manifest.MemoryLimit
			c := price * (float64(cont.Manifest.CPUShares) / float64(total_cpu))
			m := price * (float64(cont.Manifest.MemoryLimit) / float64(total_mem))
			cpu_price += c
			mem_price += m
			usage.Containers[id] = &ContainerUsage{
				ID:        id,
				App:       cont.App,
				Sha:       cont.Sha,
				Env:       cont.Env,
				CPUShares: cont.Manifest.CPUShares,
				Memory:    cont.Manifest.MemoryLimit,
				CPUPrice:  toPrice(c),
				MemPrice:  toPrice(m),
			}
		}
		usage.UsedContainers = conts
		usage.UsedCPUShares = cpu
		usage.UsedMemory = mem
		usage.UsedCPUPrice = toPrice(cpu_price)
		usage.UsedMemPrice = toPrice(mem_price)
		usageMap[super] = usage
	}
	return usageMap, nil
}