/* function: stop some tasks. param: flags , task1, task2... return: */ func StopTaskHandler(w http.ResponseWriter, r *http.Request) { var response util.HttpResponse inputInfo, err := GetInfoFromRequest(&w, r) if err != nil { return } var userRequest StopRequest userRequest.Init(&inputInfo) for thisFlag, flagValue := range inputInfo.Data { switch thisFlag { case "h": userRequest.FsName["Help"], _ = strconv.ParseBool(flagValue) default: response.Set(util.INVALID_INPUT, "invalid flag of wharf stop.") io.WriteString(w, response.String()) return } } thisTask, err := checkTaskName(&w, r, userRequest.Args) if err != nil { return } if thisTask.Status == DOWN { response.Set(util.OK, "The task is already stoped.") io.WriteString(w, response.String()) return } var isStoped bool isStoped = true var outputData StopOutput for i := range thisTask.Set { unit := thisTask.Set[i] stop2delErr := StopContainer2deleteDev(unit) if stop2delErr != nil { isStoped = false outputData.Append(unit.ContainerDesc.Id, unit.HostIp, stop2delErr.Error()) } } if isStoped == true { thisTask.Status = DOWN delete(Tasks, userRequest.Args[0]) Tasks[userRequest.Args[0]] = thisTask outputData.Warning = "task " + userRequest.Args[0] + " is stopped." response.Set(util.OK, outputData.String()) io.WriteString(w, response.String()) } else { outputData.Warning = "Failed to stop " + userRequest.Args[0] response.Set(util.SERVER_ERROR, outputData.String()) io.WriteString(w, response.String()) } return }
/* function: Rm some tasks. param: flags , task1, task2... */ func RmTaskHandler(w http.ResponseWriter, r *http.Request) { var response util.HttpResponse inputInfo, err := GetInfoFromRequest(&w, r) if err != nil { return } //flag parse var userRequest RmRequest userRequest.Init(&inputInfo) for thisFlag, flagValue := range inputInfo.Data { switch thisFlag { case "h": userRequest.FsName["Help"], _ = strconv.ParseBool(flagValue) default: response.Set(util.INVALID_INPUT, "invalid flag of wharf stop.") io.WriteString(w, response.String()) return } } thisTask, err := checkTaskName(&w, r, userRequest.Args) if err != nil { return } if thisTask.Status != DOWN { response.Set(util.INVALID_INPUT, "The task is not stoped yet.") io.WriteString(w, response.String()) return } var isRemoved bool isRemoved = true var outputData StopOutput for i := range thisTask.Set { unit := thisTask.Set[i] rmErr := removeContainerOnHost(unit.ContainerDesc.Id, unit.HostIp) if rmErr != nil { isRemoved = false outputData.Append(unit.ContainerDesc.Id, unit.HostIp, rmErr.Error()) } clearTaskInGres(unit) } if isRemoved == true { delete(Tasks, userRequest.Args[0]) outputData.Warning = "task " + userRequest.Args[0] + " is removed." response.Set(util.OK, outputData.String()) io.WriteString(w, response.String()) } else { outputData.Warning = "Failed to remove" + userRequest.Args[0] response.Set(util.SERVER_ERROR, outputData.String()) io.WriteString(w, response.String()) } return }
/* function: start some tasks. param: flags , task1, task2... */ func StartTaskHandler(w http.ResponseWriter, r *http.Request) { var response util.HttpResponse inputInfo, err := GetInfoFromRequest(&w, r) if err != nil { return } var userRequest StartRequest userRequest.Init(&inputInfo) for thisFlag, flagValue := range inputInfo.Data { switch thisFlag { case "h": userRequest.FsName["Help"], _ = strconv.ParseBool(flagValue) default: response.Set("404-invalid input", "invalid flag of wharf start.") io.WriteString(w, response.String()) return } } thisTask, err := checkTaskName(&w, r, userRequest.Args) if err != nil { return } if thisTask.Status == RUNNING { response.Set(util.OK, "The task is already started.") io.WriteString(w, response.String()) return } //start each ct accoring to the task var isStarted bool isStarted = true var outputData StartOutput for i := range thisTask.Set { unit := thisTask.Set[i] start2delErr := startContainerWithIP(&(thisTask.Set[i])) //hostip , contaienr id, container ip if start2delErr != nil { isStarted = false outputData.Append(unit.ContainerDesc.Id, unit.HostIp, start2delErr.Error()) } } if isStarted == true { thisTask.Status = RUNNING delete(Tasks, userRequest.Args[0]) Tasks[userRequest.Args[0]] = thisTask outputData.Warning = "task " + userRequest.Args[0] + " is started." response.Set(util.OK, outputData.String()) io.WriteString(w, response.String()) } else { outputData.Warning = "Failed to start " + userRequest.Args[0] response.Set(util.SERVER_ERROR, outputData.String()) io.WriteString(w, response.String()) } return }
/* function: check if the user provides valid taskname. return: */ func checkTaskName(w *http.ResponseWriter, r *http.Request, Args []string) (thisTask Task, err error) { var response util.HttpResponse if len(Args) < 1 { response.Set(util.INVALID_INPUT, "You must provide one taskname to the command.") io.WriteString(*w, response.String()) return thisTask, errors.New("Taskname is not provided.") } thistask, exists := Tasks[Args[0]] if !exists { response.Set(util.INVALID_INPUT, "There is no task with the name of "+`'`+Args[0]+`'`) io.WriteString(*w, response.String()) return thistask, errors.New("Taskname is invalid.") } return thistask, nil }
/*Function: get the information in http.Request to 'inputInfo'. return value: 1)succeed: the data was stored 'inputInfo' 2)Fail:the error information is write into 'w' */ func GetInfoFromRequest(w *http.ResponseWriter, r *http.Request) (inputInfo util.SendCmd, err error) { var response util.HttpResponse var input []byte input, err = util.ReadContentFromHttpRequest(r) if err != nil { response.Set(util.SERVER_ERROR, err.Error()+"in server Handler()") io.WriteString(*w, response.String()) return inputInfo, err } err = json.Unmarshal(input, &inputInfo) if err != nil { response.Set(util.SERVER_ERROR, err.Error()+"in Server TaskHandler()") io.WriteString(*w, response.String()) return inputInfo, err } return inputInfo, nil }
/*function:create task from the user command. we will create the task and store it in Tasks param: r: r.Body include the string of the user command w: w.Body include the result of the create.response will be marshal to w. */ func CreateTaskHandler(w http.ResponseWriter, r *http.Request) { var response util.HttpResponse var thisTask Task response.Status = util.INVALID_INPUT var contents []byte contents = make([]byte, 1000) length, err := r.Body.Read(contents) if err != nil && err != io.EOF { fmt.Fprintf(os.Stderr, "CreateHandler: can not read from http resposeWriter\n") fmt.Fprintf(os.Stderr, "%s", err) response.Warnings = []string{"CreateHandler: can not read from http resposeWriter\n" + err.Error()} io.WriteString(w, response.String()) return } var res util.SendCmd if *FlagDebug { fmt.Println("contents:", string(contents)) } //make sure the char in contents should not include '\0' contentsRight := contents[:length] errunmarshal := json.Unmarshal(contentsRight, &res) if errunmarshal != nil { fmt.Fprintf(os.Stderr, "CreateHandler: Unmarshal failed for contents: ") fmt.Fprintf(os.Stderr, "%s", errunmarshal) response.Warnings = []string{"CreateHandler: Unmarshal failed for contents: " + errunmarshal.Error()} io.WriteString(w, response.String()) return } else { //now we will create our task here: filter, allocator, (image server) ,scheduler var userRequest CreateRequest userRequest.Init() for thisflag, flagvalue := range res.Data { switch { case strings.EqualFold(thisflag, "i"): userRequest.ImageName = flagvalue case strings.EqualFold(thisflag, "t"): userRequest.TypeName = flagvalue if !strings.EqualFold(flagvalue, "mpi") && !strings.EqualFold(flagvalue, "single") { fmt.Fprintf(os.Stderr, `the type of the task is not supported yet. Only "single" and "mpi" is supported.`) response.Warnings = []string{`the type of the task is not supported yet. Only "single" and "mpi" is supported.`} io.WriteString(w, response.String()) return } case strings.EqualFold(thisflag, "n"): userRequest.TaskName = flagvalue case strings.EqualFold(thisflag, "s"): userRequest.Stratergy = flagvalue if !strings.EqualFold(thisflag, "MEM") && !strings.EqualFold(thisflag, "COM") { response.Warnings = []string{`Only MEM and COM are valid for -s flag`} io.WriteString(w, response.String()) return } case strings.EqualFold(thisflag, "c"): userRequest.TotalCpuNum, _ = strconv.Atoi(flagvalue) case strings.EqualFold(thisflag, "C"): userRequest.ContainerNumMax, _ = strconv.Atoi(flagvalue) case strings.EqualFold(thisflag, "l"): value, _ := strconv.ParseFloat(flagvalue, 32) userRequest.OverLoadMax = float32(value) case strings.EqualFold(thisflag, "f"): filename := flagvalue readerme, openerr := os.Open(filename) if openerr != nil { fmt.Fprintf(os.Stderr, "CreateHandler:%s", openerr) response.Warnings = []string{"CreateHandler" + openerr.Error()} io.WriteString(w, response.String()) return } unmarshalerr := util.UnmarshalReader(readerme, &(userRequest.ResNode)) if unmarshalerr != nil { response.Warnings = []string{unmarshalerr.Error()} io.WriteString(w, response.String()) } default: fmt.Fprintf(os.Stderr, "CreateHandler: %s flag invalid", thisflag) response.Warnings = []string{"CreateHandler: " + thisflag + "flag invalid"} io.WriteString(w, response.String()) return } } var err error endpoint := []string{"http://" + MasterConfig.EtcdNode.Ip + ":" + MasterConfig.EtcdNode.Port} err = UpdateEtcdForUse(endpoint, MasterConfig.EtcdNode.Key, true, true) if err != nil { if *FlagDebug { util.PrintErr("Failded to Etcd data!") } response.Warnings = []string{err.Error()} io.WriteString(w, response.String()) return } //Debug if *FlagDebug { util.PrintErr("Etcd data has been updated!") } err = UpdateGres() if err != nil { response.Warnings = []string{err.Error()} io.WriteString(w, response.String()) return } //Debug if *FlagDebug { util.PrintErr("Gres has been updated!With ", len(Gres), " terms left.") if len(Gres) == 0 { util.PrintErr("Error: ", "0 node can be used in Gres") } } err = Filter(userRequest) //Debug if *FlagDebug { util.PrintErr("Rres has been Filtered!, with ", len(Rres), " terms left") } err = Allocate(userRequest) if err != nil { io.WriteString(w, err.Error()) io.WriteString(w, response.String()) return } //Debug if *FlagDebug { util.PrintErr("Allocate complished for the create task! ", len(Ares), " containers will be created!") } thisTask.Init(userRequest, len(Ares)) err = ImageTransport(&thisTask) if err != nil { io.WriteString(w, err.Error()) io.WriteString(w, response.String()) return } //create container,start it, bind ip err = CreateContainer2Ares(&thisTask) if err != nil { //Debug if *FlagDebug { util.PrintErr("CreateContainer2Ares failed:", err.Error()) } response.Set(util.SERVER_ERROR, err.Error()) io.WriteString(w, response.String()) return } thisTask.CreatedTime = time.Now() thisTask.Status = RUNNING Tasks[userRequest.TaskName] = thisTask LatestTask = userRequest.TaskName response.Set(util.OK, thisTask.Cmd.TaskName) io.WriteString(w, response.String()) } }
/*List the information about one or more tasks. The information is not in detai */ func ListTaskHandler(w http.ResponseWriter, r *http.Request) { //the return value :response var response util.HttpResponse inputInfo, err := GetInfoFromRequest(&w, r) if err != nil { return } var userRequest PsRequest userRequest.Init() for thisFlag, flagValue := range inputInfo.Data { switch thisFlag { case "a": userRequest.All, _ = strconv.ParseBool(flagValue) case "l": userRequest.Latest, _ = strconv.ParseBool(flagValue) case "n": userRequest.Name = flagValue case "i": userRequest.Image = flagValue case "t": userRequest.Type = flagValue default: response.Set(util.INVALID_INPUT, "invalid flag of wharf ps.") io.WriteString(w, response.String()) return } } //flags conflict if userRequest.All && userRequest.Latest || userRequest.All && userRequest.Name != "" || userRequest.Latest && userRequest.Name != "" { response.Set(util.INVALID_INPUT, "flags are conflicting with each other.") io.WriteString(w, response.String()) return } var psIterm PsOutput //task name is set || latest is set if userRequest.Name != "" || userRequest.Latest { if userRequest.Latest { userRequest.Name = LatestTask } thisTask, exists := Tasks[userRequest.Name] if !exists { response.Set(util.INVALID_INPUT, `No such task with name of "`+userRequest.Name+`"`) io.WriteString(w, response.String()) return } else { fillPSOutpusWithTask(&psIterm, &thisTask) data, _ := json.Marshal(psIterm) response.Set(util.OK, string(data)) io.WriteString(w, response.String()) return } } //traverse all the task in Tasks for _, thisTask := range Tasks { response.Status = util.OK if (userRequest.All == true || thisTask.Status == RUNNING) && (userRequest.Image == "" || thisTask.Cmd.ImageName == userRequest.Image) && (userRequest.Type == "" || thisTask.Cmd.TypeName == userRequest.Type) { fillPSOutpusWithTask(&psIterm, &thisTask) data, _ := json.Marshal(psIterm) response.Append(string(data)) } io.WriteString(w, response.String()) } return }
/*insect the detail informatin about only one task.*/ func InspectTaskHandler(w http.ResponseWriter, r *http.Request) { var response util.HttpResponse inputInfo, err := GetInfoFromRequest(&w, r) if err != nil { return } var userRequest InspectReqest userRequest.Init() for thisFlag, flagValue := range inputInfo.Data { switch thisFlag { case "f": userRequest.Field = flagValue default: response.Set(util.INVALID_INPUT, "invalid flag of wharf inspect.") io.WriteString(w, response.String()) return } } //must contain one taskname if len(inputInfo.Args) != 1 { response.Set(util.INVALID_INPUT, "You must provide one and only taskname to insepect.") io.WriteString(w, response.String()) return } thistask, exists := Tasks[inputInfo.Args[0]] if !exists { response.Set(util.INVALID_INPUT, "There is no task with the name of "+`'`+inputInfo.Args[0]+`'`) io.WriteString(w, response.String()) return } var outputData InspectOutput outputData.GetData(thistask) if userRequest.Field == "" { var outputByte []byte outputByte, err = json.Marshal(outputData) if err != nil { response.Set(util.SERVER_ERROR, err.Error()) } else { response.Set(util.OK, string(outputByte)) } } else { immutable := reflect.ValueOf(outputData) fieldValue := userRequest.Field if fieldValue[0:1] == `.` { fieldValue = fieldValue[1:] } itermsStr := strings.Split(fieldValue, ".") for i := range itermsStr { immutable = immutable.FieldByName(itermsStr[i]) } response.Set(util.OK, immutable.String()) } io.WriteString(w, response.String()) return }