func scheduleAndAttach(jobid string, config docker.Config) { client, err := lc.New(hostid) if err != nil { log.Fatal(err) } conn, attachWait, err := client.Attach(&lorne.AttachReq{ JobID: jobid, Flags: lorne.AttachFlagStdout | lorne.AttachFlagStderr | lorne.AttachFlagStdin | lorne.AttachFlagStream, }, true) if err != nil { log.Fatal(err) } schedReq := &sampi.ScheduleReq{ Incremental: true, HostJobs: map[string][]*sampi.Job{hostid: {{ID: jobid, Config: &config}}}, } if _, err := sched.Schedule(schedReq); err != nil { log.Fatal(err) } if err := attachWait(); err != nil { log.Fatal(err) } go func() { io.Copy(conn, os.Stdin) conn.CloseWrite() }() scanner := bufio.NewScanner(conn) for scanner.Scan() { fmt.Fprintln(os.Stdout, scanner.Text()[8:]) } conn.Close() }
func batchHandler(w http.ResponseWriter, r *http.Request) { sched, err := jobs.New() if error500(w, err) { return } s, err := services.Services("flynn-lorne", services.DefaultTimeout) if error500(w, err) { return } hostid := s[0].Attrs["id"] jobid := jobs.RandomJobID("batch") host, err := hosts.New(hostid) if error500(w, err) { return } conn, attachWait, err := host.Attach(&lorne.AttachReq{ JobID: jobid, Flags: lorne.AttachFlagStdout | lorne.AttachFlagStderr | lorne.AttachFlagStdin | lorne.AttachFlagStream, }, true) if error500(w, err) { return } config := docker.Config{ Image: strings.TrimPrefix(r.URL.Path, "/batch/"), Cmd: strings.Split(r.URL.RawQuery, "+"), Tty: false, AttachStdin: false, AttachStdout: false, AttachStderr: false, OpenStdin: false, StdinOnce: false, } schedReq := &sampi.ScheduleReq{ Incremental: true, HostJobs: map[string][]*sampi.Job{ hostid: {{ID: jobid, Config: &config}}}, } _, err = sched.Schedule(schedReq) if error500(w, err) { return } err = attachWait() if error500(w, err) { return } fw := FlushWriter(w) scanner := bufio.NewScanner(conn) for scanner.Scan() { fmt.Fprintln(fw, scanner.Text()) } conn.Close() fw.Write([]byte("\n")) }
func getPort(hostid, jobid string) string { host, err := hosts.New(hostid) assert(err) job, err := host.GetJob(jobid) assert(err) for portspec := range job.Job.Config.ExposedPorts { return strings.Split(portspec, "/")[0] } return "" }
func init() { var err error sched, err = sc.New() if err != nil { log.Fatal(err) } hostid = findHost() host, err = lc.New(hostid) if err != nil { log.Fatal(err) } }
func init() { var err error sd, err = discover.NewClient() if err != nil { log.Fatal(err) } sched, err = sc.New() if err != nil { log.Fatal(err) } hostid = findHost() host, err = lc.New(hostid) if err != nil { log.Fatal(err) } }
func runJobs(cmd *Command, args []string) { if len(args) != 0 { cmd.printUsage() os.Exit(2) } err := discoverd.Connect(getTarget() + ":55002") // TODO: fix this assert(err) services, err := discoverd.Services("flynn-lorne", discoverd.DefaultTimeout) assert(err) for _, service := range services { host, err := client.New(service.Attrs["id"]) assert(err) jobs, err := host.JobList() for k, _ := range jobs { fmt.Println(k, "\t", "["+service.Attrs["id"]+"]") } } }
// POST /apps/{app_id}/formation/{formation_id} func changeFormation(u *url.URL, h http.Header, req *Formation) (int, http.Header, *Formation, error) { state, err := scheduler.State() if err != nil { log.Println("scheduler state error", err) return 500, nil, nil, err } q := u.Query() req.Type = q.Get("formation_id") prefix := q.Get("app_id") + "-" + req.Type + "." var jobs []*sampi.Job for _, host := range state { for _, job := range host.Jobs { if strings.HasPrefix(job.ID, prefix) { if job.Attributes == nil { job.Attributes = make(map[string]string) } job.Attributes["host_id"] = host.ID jobs = append(jobs, job) } } } if req.Quantity < 0 { req.Quantity = 0 } diff := req.Quantity - len(jobs) log.Printf("have %d %s, diff %d", len(jobs), req.Type, diff) if diff > 0 { config := &docker.Config{ Image: "flynn/slugrunner", Cmd: []string{"start", req.Type}, AttachStdout: true, AttachStderr: true, Env: []string{"SLUG_URL=http://" + shelfURL() + "/" + q.Get("app_id") + ".tgz"}, } if req.Type == "web" { config.Env = append(config.Env, "SD_NAME="+q.Get("app_id")) } schedReq := &sampi.ScheduleReq{ HostJobs: make(map[string][]*sampi.Job), } outer: for { for host := range state { schedReq.HostJobs[host] = append(schedReq.HostJobs[host], &sampi.Job{ID: prefix + randomID(), TCPPorts: 1, Config: config}) diff-- if diff == 0 { break outer } } } res, err := scheduler.Schedule(schedReq) if err != nil || !res.Success { log.Println("schedule error", err) return 500, nil, nil, err } } else if diff < 0 { for _, job := range jobs[:-diff] { host, err := lornec.New(job.Attributes["host_id"]) if err != nil { log.Println("error connecting to", job.Attributes["host_id"], err) continue } if err := host.StopJob(job.ID); err != nil { log.Println("error stopping", job.ID, "on", job.Attributes["host_id"], err) } } } return 200, nil, req, nil }