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 }
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 }
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 }