/*function: remove a container with id of "id" ont host "hostIP". return value: nil, when no error */ func removeContainerOnHost(id, hostIp string) error { if *FlagDebug { util.PrintErr("[ removeContainerOnHost ]") } endpoint := "http://" + hostIp + ":" + MasterConfig.Docker.Port path := `/containers/` + id + `?v=1` request, err := http.NewRequest("DELETE", endpoint+path, strings.NewReader("")) if err != nil { util.PrintErr("http.NewRequest: ", err.Error()) return errors.New("http.NewRequest: " + err.Error()) } resp, err := http.DefaultClient.Do(request) if resp != nil { defer resp.Body.Close() } if err != nil { util.PrintErr("http.DefaultClient.Do ", err.Error()) return errors.New("http.DefaultClient.Do " + err.Error()) } //err == nil if !strings.HasPrefix(resp.Status, "204") { util.PrintErr("resp.Status do not has prefix of 200 --", resp.Status) return errors.New("resp.Status do not has prefix of 200 --" + resp.Status) } else { return nil } }
func removeImageOnHost(nameOrId, hostIp string) error { if *FlagDebug { util.PrintErr("[ removeImageOnHost ]") } endpoint := "http://" + hostIp + ":" + MasterConfig.Docker.Port path := `/images/` + nameOrId request, err := http.NewRequest("DELETE", endpoint+path, strings.NewReader("")) if err != nil { util.PrintErr("http.NewRequest: ", err.Error()) return errors.New("http.NewRequest: " + err.Error()) } resp, err := http.DefaultClient.Do(request) if err != nil { util.PrintErr("http.DefaultClient.Do ", err.Error()) return errors.New("http.DefaultClient.Do " + err.Error()) } if resp != nil { defer resp.Body.Close() } //err == nil if !strings.HasPrefix(resp.Status, "200") { return errors.New(resp.Status) } else { return nil } }
//Init net server, etcd server func InitServer() { err := initEtcd() if err != nil { util.PrintErr(err.Error()) os.Exit(1) } initNetwork() starterr := util.StartDocker(MasterConfig.Docker.Bridge) if starterr != nil { util.PrintErr(starterr) os.Exit(1) } Gres = make(map[string]Res, 1) Rres = make(map[string]Res, 1) Ares = make(map[string]Res, 1) Tasks = make(map[string]Task, 1) http.HandleFunc("/ps", ListTaskHandler) http.HandleFunc("/create", CreateTaskHandler) http.HandleFunc("/inspect", InspectTaskHandler) http.HandleFunc("/stop", StopTaskHandler) http.HandleFunc("/start", StartTaskHandler) http.HandleFunc("/rm", RmTaskHandler) errhttp := http.ListenAndServe(":"+MasterConfig.Server.Port, nil) if errhttp != nil { log.Fatal("InitServer: ListenAndServe ", errhttp) } }
/*function: create container according to Ares fill the task struct for the taskname and bind ip to containers, and start them param: *Ares:global param tasknamep: the task to be filled--containerDesc.Id, hostIp, HostMachine return value: nil, if succeed; error , if fail. */ func CreateContainer2Ares(tasknamep *Task) error { if *FlagDebug { util.PrintErr("[ CreateContainer2Ares ]") } var index int for ip, resData := range Ares { tasknamep.Set[index].HostIp = ip /* tasknamep.Set[index].HostMachine = resData.Node */ thisContainerIp, getiperr := GetFreeIP() if getiperr != nil { return getiperr } tasknamep.Set[index].ContainerIp = thisContainerIp.String() var opts CreateContainerOptions opts.Init() fields := strings.Split(thisContainerIp.String(), ".") first, _ := strconv.Atoi(fields[2]) second, _ := strconv.Atoi(fields[3]) hostnameIndex := first*256 + second opts.Hostname = strconv.Itoa(hostnameIndex) //we set the container hostname as its ip index //modifiy: if Docker_nr all = 0, the node will be filter out opts.Cpuset = util.GetNozeroIndex(resData.Docker_nr) opts.Image = tasknamep.Cmd.ImageName endpoint := ip + ":" + MasterConfig.Docker.Port thisContainer, createerr := CreateContainer(endpoint, opts) if createerr != nil { return createerr } else { tasknamep.Set[index].ContainerDesc.Id = thisContainer.Id tasknamep.Set[index].Docker_nr = resData.Docker_nr } starterr := StartContainerOnHost(thisContainer.Id, ip) if starterr != nil { return starterr } if *FlagDebug { util.PrintErr("container ", thisContainer.Id, "is started on host", ip, "\n") } networkName, binderr := BindIpWithContainerOnHost(thisContainerIp.String(), thisContainer.Id, ip) if binderr != nil { return binderr } tasknamep.Set[index].Nic = networkName index++ } return nil }
/* function :Print the subcommand usage*/ func subcommandUsage(cont *cmdCont) { program := PROGRAM switch cont.name { case "version": fmt.Fprintf(os.Stderr, "Usage of %s %s:\n", program, cont.name) fmt.Fprintf(os.Stderr, ` Just use "wharf version"`+"\n") case "create": fmt.Fprintf(os.Stderr, "Usage: %s %s [OPTIONS]\n", program, cont.name) fmt.Fprintf(os.Stderr, `Create a task from user command`+"\n") case "ps": fmt.Fprintf(os.Stderr, "Usage: %s %s [OPTIONS]\n", program, cont.name) fmt.Fprintf(os.Stderr, `List one or more tasks`+"\n") case "inspect": fmt.Fprintf(os.Stderr, "Usage: %s %s [OPTIONS] TASKNAME\n", program, cont.name) fmt.Fprintf(os.Stderr, `Return low-level information on a task`+"\n") case "stop": fmt.Fprintf(os.Stderr, "Usage: %s %s [OPTIONS] TASKNAME [TASKNAME...]\n", program, cont.name) fmt.Fprintf(os.Stderr, `Stop a running task:stop all the container related to this task.The Ip and the virtual network device will not be given out by this command.`+"\n") case "start": fmt.Fprintf(os.Stderr, "Usage: %s %s [OPTIONS] TASKNAME [TASKNAME...]\n", program, cont.name) fmt.Fprintf(os.Stderr, `Restart a stopped task.`+"\n") case "rm": fmt.Fprintf(os.Stderr, "Usage: %s %s [OPTIONS] TASKNAME [TASKNAME...]\n", program, cont.name) fmt.Fprintf(os.Stderr, `Restart a stopped task.`+"\n") default: } // should only output sub command flags, ignore h flag. fs := matchingCmd.command.Flags(flag.NewFlagSet(cont.name, flag.ContinueOnError)) fs.PrintDefaults() util.PrintErr("\n" + cont.desc + "\n") linewidth := 160 for index := range cont.validFlags { each := cont.validFlags[index] if len(each.usage) < linewidth { util.PrintErr("-" + each.name + " " + each.usage) } else { util.PrintErr("-" + each.name + " " + each.usage[:linewidth]) util.PrintErr(" " + each.usage[linewidth:]) } /* util.PrintErr("-", eflag) */ } if len(cont.requiredFlags) > 0 { fmt.Fprintf(os.Stderr, "\nrequired flags:\n") fmt.Fprintf(os.Stderr, " %s\n\n", strings.Join(cont.requiredFlags, ", ")) } }
func Load2DelwithHead(info util.ImageTransportHeadAPI) error { if *FlagDebug { util.PrintErr("[ Load2DelwithHead ]") } tarFileName := info.FileName err := RmTarImageOnHost(tarFileName, info.Server) if err != nil { return err } var chs []chan error chs = make([]chan error, len(info.Nodes)) for index := range info.Nodes { chs[index] = make(chan error) hostIp := info.Net + "." + info.Nodes[index] go load2del(tarFileName, hostIp, chs[index]) } for i := 0; i < len(info.Nodes); i++ { value := <-chs[i] if value != nil { return value } } return nil }
func deleteDevice(hostIp, nicName string) error { if *FlagDebug { util.PrintErr("[ deleteDevice ]") } var response util.HttpResponse endpoint := "http://" + hostIp + ":" + MasterConfig.Resource.Port path := `/del_dev` res, err := http.Post(endpoint+path, util.POSTTYPE, strings.NewReader(nicName)) if err != nil { return err } if strings.HasPrefix(res.Status, "200") { err = util.ReadContentFromHttpResponse(res, &response) if err != nil { return err } if strings.HasPrefix(response.Status, "200") { return nil } else { return errors.New(response.Status) } } else { return errors.New(res.Status) } }
/*This func will create container in endpoint according to opts, and return value of Container para: endpoint: ip:port */ func CreateContainer(endpoint string, opts CreateContainerOptions) (*CreateContainerReturn, error) { if *FlagDebug { util.PrintErr("[ CreateContainer ]") } path := "/containers/create?" url := "http://" + endpoint + path contentType := "application/json" data, _ := json.Marshal(opts) res, err := http.Post(url, contentType, strings.NewReader(string(data))) if err != nil { return nil, err } else if !strings.HasPrefix(res.Status, "201") { return nil, errors.New(res.Status) } else { defer res.Body.Close() contents, _ := ioutil.ReadAll(res.Body) var returnContainer CreateContainerReturn unmarshalerr := json.Unmarshal(contents, &returnContainer) if unmarshalerr != nil { return nil, unmarshalerr } else { return &returnContainer, nil } } }
/*This func will inspect container in endpoint according to opts, and return value of Container para: endpoint: ip:port */ func InspectContainer(endpoint string, opts InspectReq) (ct Container, err error) { if *FlagDebug { util.PrintErr("[ InspectContainer ]") } path := "/containers/" + opts.Id + "/json" url := "http://" + endpoint + path res, err := http.Get(url) if err != nil { return ct, err } else { if strings.HasPrefix(res.Status, "404") { return ct, errors.New(res.Status) } else if strings.HasPrefix(res.Status, "200") { defer res.Body.Close() contents, _ := ioutil.ReadAll(res.Body) unmarshalerr := json.Unmarshal(contents, &ct) if unmarshalerr != nil { return ct, unmarshalerr } else { return ct, nil } } else { return ct, errors.New(res.Status) } } }
func LoadTarOnHost(tarFileName, hostIp string) error { url := `http://` + hostIp + `:` + MasterConfig.Image.Port + `/load_image` if *FlagDebug { util.PrintErr("[ LoadTarOnHost ]") util.PrintErr(url) } resp, err := http.Post(url, util.POSTTYPE, strings.NewReader(tarFileName)) if err != nil { res := errors.New("Load tar on host Failed:" + err.Error()) util.PrintErr(res) return res } else if !strings.HasPrefix(resp.Status, "200") { res := errors.New("Load tar on host Failed:" + resp.Status) util.PrintErr(res) return res } else { return nil } }
/*search if IMAGE is available on hostIP*/ func searchImageOnHost(nameOrId, hostIp string) (bool, error) { port := MasterConfig.Docker.Port if port == string("") { port = "4243" } endpoint := hostIp + ":" + port path := `/images` url := `http://` + endpoint + path + `/` + nameOrId + `/` + `json` if *FlagDebug { util.PrintErr("[ searchImageOnHost ]") util.PrintErr(" ", url) } resp, err := http.Get(url) if err != nil { return false, err } else if !strings.HasPrefix(resp.Status, "200") { return false, errors.New(resp.Status) } else { return true, nil } }
/*give subcommad to httpserver, this acted as a http request return value: error occur:Fail to post, or the server do no answer. error nil;the data from the server */ func (e *Subcommand) Run(arg []string) ([]byte, error) { var contents []byte fs := e.fs if *FlagDebug { fmt.Fprintf(os.Stderr, "subcommand %s will be executed\n", e.name) } fs.Visit(storeFlag) var tobesend util.SendCmd tobesend.Data = sendflags tobesend.Args = arg value, err := json.Marshal(&tobesend) if err != nil { panic(err) return contents, err } else { var url string url = "http://" + server.MasterConfig.Server.Ip + ":" + server.MasterConfig.Server.Port + "/" + e.name if *FlagDebug { fmt.Fprintf(os.Stderr, "the value of post data is %s\n", string(value)) } res, err2 := http.Post(url, `appliction/x-www-form-urlencoded`, strings.NewReader(string(value))) if err2 != nil { fmt.Fprintf(os.Stderr, "Error: Fail to Post: %s", err2) return contents, err2 } else if !strings.HasPrefix(res.Status, "200") { util.PrintErr("Error: Server Fail to handle this request, " + res.Status) os.Exit(1) return contents, errors.New("Error: Server Fail to handle this request, " + res.Status) } else { defer res.Body.Close() var err3 error contents = make([]byte, 1000) contents, err3 = ioutil.ReadAll(res.Body) if err3 != nil { fmt.Fprintf(os.Stderr, "%s", err3) return contents, err3 } else { if *FlagDebug { fmt.Fprintf(os.Stderr, "the return data of post is %s\n", string(contents)) } return contents, nil } } } return contents, nil }
func RmTarImageOnHost(tarFileName, hostIp string) error { if *FlagDebug { util.PrintErr("[ RmTarImageOnHost ]") } url := `http://` + hostIp + `:` + MasterConfig.Image.Port + `/rm_tarfile` resp, err := http.Post(url, util.POSTTYPE, strings.NewReader(tarFileName)) if err != nil { return errors.New("Delete tar on host Failed:" + err.Error()) } else if !strings.HasPrefix(resp.Status, "200") { return errors.New("Delete tar on host Failed:" + resp.Status) } else { return nil } }
func SaveImageOnHost(nameOrId, hostIp string) error { if *FlagDebug { util.PrintErr("[ SaveImageOnHost ]") util.PrintErr(" on ", hostIp) } var info util.Image2TarAPI info = util.Image2TarAPI{Image: nameOrId, TarFileName: nameOrId + `.tar`} data, _ := json.Marshal(info) var url string url = `http://` + hostIp + `:` + MasterConfig.Image.Port + `/save_image` resp, err := http.Post(url, util.POSTTYPE, strings.NewReader(string(data))) if err != nil { res := errors.New("SaveImageOnHost: " + err.Error()) util.PrintErr(res) return res } else if !strings.HasPrefix(resp.Status, "200") { res := errors.New("SaveImageOnHost: " + resp.Status) util.PrintErr(res) return res } else { return nil } }
func TransportImageWithHead(info util.ImageTransportHeadAPI) error { if *FlagDebug { util.PrintErr("[ TransportImagewithHead ]") } data, _ := json.Marshal(info) url := `http://` + info.Server + `:` + MasterConfig.Image.Port + `/transport_image` resp, err := http.Post(url, util.POSTTYPE, strings.NewReader(string(data))) if err != nil { return err } else if !strings.HasPrefix(resp.Status, "200") { return errors.New("TransportImagewithHead: " + resp.Status) } else { return nil } }
func load2del(tarFileName string, hostIp string, ch chan error) { if *FlagDebug { util.PrintErr("[ load2del ]") } loaderr := LoadTarOnHost(tarFileName, hostIp) if loaderr != nil { ch <- loaderr return } delerr := RmTarImageOnHost(tarFileName, hostIp) if delerr != nil { ch <- delerr return } ch <- nil return }
/*function: stop a container with id of "id" ont host "hostIP". This will give out a http request to the docker deamon on "HostIP". return value: nil, when no error */ func StopContainerOnHost(id, hostIp string) error { if *FlagDebug { util.PrintErr("[ StopContainerOnHost]") } endpoint := "http://" + hostIp + ":" + MasterConfig.Docker.Port path := `/containers/` + id + `/stop?t=1` res, err := http.Post(endpoint+path, util.POSTTYPE, strings.NewReader("")) if err != nil { return err } //err == nil if strings.HasPrefix(res.Status, "204") { return nil } else { return errors.New(res.Status + " from docker daemon") } }
/* function:start a container according to a CalUnit. */ func startContainerWithIP(unit *CalUnit) error { //hostip , contaienr id, container ip if *FlagDebug { util.PrintErr("[ startContainerWithIP ]") } containerId := unit.ContainerDesc.Id containerIp := unit.ContainerIp hostIp := unit.HostIp starterr := StartContainerOnHost(containerId, hostIp) if starterr != nil { return starterr } else { devname, binderr := BindIpWithContainerOnHost(containerIp, containerId, hostIp) if binderr == nil { unit.Nic = devname } return binderr } }
/* carefull: in this function, image name >> tarfilename */ func partition(imageNodes []string, emptyNodes []string, imageName string) []util.ImageTransportHeadAPI { if *FlagDebug { util.PrintErr("[partition]") } var transportHeads []util.ImageTransportHeadAPI var thisHead util.ImageTransportHeadAPI m := len(imageNodes) n := len(emptyNodes) fmt.Println("imagenodes, emptyNodes:", m, n) num := n / m remain := n % m var i int var emptyIndex int netIp := MasterConfig.Network.Net thisHead.Net = util.GetNetOfBIp(netIp.String()) thisHead.DataIndex = 0 thisHead.FileName = imageName + ".tar" //make sure this filename for i = 0; i < remain; i++ { thisHead.Server = imageNodes[i] thisHead.Nodes = make([]string, num+1) for j := 0; j < num+1; j++ { thisHead.Nodes[j] = util.GetHostOfBIp(emptyNodes[emptyIndex]) emptyIndex++ } transportHeads = append(transportHeads, thisHead) } for ; i < m && num != 0; i++ { thisHead.Server = imageNodes[i] thisHead.Nodes = make([]string, num) for j := 0; j < num; j++ { thisHead.Nodes[j] = util.GetHostOfBIp(emptyNodes[emptyIndex]) emptyIndex++ } transportHeads = append(transportHeads, thisHead) } return transportHeads }
func saveTransLoadDel(imageName string, transportHead util.ImageTransportHeadAPI, ch chan error) error { if *FlagDebug { util.PrintErr("[ saveTransLoadDel ]") } err := SaveImageOnHost(imageName, transportHead.Server) if err != nil { ch <- err return err } transerr := TransportImageWithHead(transportHead) if transerr != nil { ch <- transerr return transerr } load2delerr := Load2DelwithHead(transportHead) if load2delerr != nil { ch <- load2delerr return load2delerr } ch <- nil return nil }
/*function: bind a ip to a container in a host. This is a http request posted to the "docker server". Actrually, it is handler by module of resource. param: ip: the ip to be bind. id: the id of the container hostip:the hostip return value: networkName :the virtual device of the eth */ func BindIpWithContainerOnHost(containerIp string, id string, hostIp string) (string, error) { if *FlagDebug { util.PrintErr("[ BindIpWithContainerOnHost ]") } var networkName string port := MasterConfig.Resource.Port endpoint := "http://" + hostIp + ":" + port url := endpoint + `/bindip2container` var ctn_ip util.Container2Ip ctn_ip = util.Container2Ip{id, containerIp} data, jsonerr := json.Marshal(ctn_ip) if jsonerr != nil { return networkName, jsonerr } res, err := http.Post(url, util.POSTTYPE, strings.NewReader(string(data))) if err != nil { return networkName, err } //err == nil defer res.Body.Close() data, _ = ioutil.ReadAll(res.Body) var result util.HttpResponse jsonerr = json.Unmarshal(data, &result) if jsonerr != nil { return networkName, jsonerr } else { var err error if strings.HasPrefix(result.Status, "200") { networkName = result.Warnings[0] err = nil } else { err = errors.New(result.Warnings[0]) } return networkName, err } }
/* Before we create a task, we should update the contents in etcd: 1.Get the contents for each node in endpoint of etcd 2.If the status of the node is Down, Delete it from etcd ----is not Down:Update it through module resource 2.1 if Update succeed, set data, reset Failtime, set Status to UP 2.2 if Update Failed, Failtime++ if Failtime >= MaxFailTime, status= down if Failtime < MaxFailTime, status = alive */ func UpdateEtcdForUse(endpoint []string, key string, sort, recursive bool) error { client := etcd.NewClient(endpoint) res, err := client.Get(key, sort, recursive) if err != nil { fmt.Fprintf(os.Stderr, "get %s failed -- %s", key, err) return err } ip_nr := res.Node.Nodes.Len() if *(FlagDebug) { fmt.Println("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ UpdateEtcdForUse(): What we get in etcd is:↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓") } for i := 0; i < ip_nr; i++ { //skip the "/" to get ip ip := res.Node.Nodes[i].Key[1:] machineValue := res.Node.Nodes[i].Value if *(FlagDebug) { fmt.Println(ip, " : ", machineValue) } var machine_info util.Machine json.Unmarshal([]byte(machineValue), &machine_info) if machine_info.Status == util.DOWN { client.Delete(key, false) } else { //not down getResourceUrl := `http://` + ip + ":" + MasterConfig.Resource.Port + `/` + `get_resource` resp, err := http.Get(getResourceUrl) var getSucceed bool //the default is false getSucceed = false if err == nil { defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) var resp util.HttpResponse jsonerr := json.Unmarshal(body, &resp) if jsonerr != nil { if *FlagDebug { util.PrintErr("Function-UpdateEtcdForUse: json err") util.PrintErr("try to unmarshal data failed:", string(body)) } return jsonerr } if strings.HasPrefix(resp.Status, "200") { getSucceed = true } else { getSucceed = false } if *(FlagDebug) && getSucceed { fmt.Println("UpdateEtcdForUse(): now the above info is updated") } } if !getSucceed { machine_info.FailTime++ if machine_info.FailTime >= util.MaxFailTime { machine_info.Status = util.DOWN } else { machine_info.Status = util.ALIVE } machineValueBytes, errmarshal := json.Marshal(machine_info) machineValue = string(machineValueBytes) if errmarshal != nil { fmt.Fprintf(os.Stderr, "UpdateEtcdForUse: marshal machine_info failed--%s", errmarshal) return errmarshal } else { _, seterr := client.Set(ip, machineValue, 0) if seterr != nil { fmt.Fprintf(os.Stderr, "UpdateEtcdForUse: can not update etcd from serve--", seterr) return seterr } } } } } if *(FlagDebug) { fmt.Println("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ UpdateEtcdForUse(): etcd data end. ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑") } return nil }
func ImageTransport(thistask *Task) error { imageName := thistask.Cmd.ImageName if imageName == "" { util.PrintErr("imageName should not be null") os.Exit(1) } if *FlagDebug { util.PrintErr("[ ImageTransport ]") } var imageNodes []string var emptyNodes []string exits, _ := searchImageOnHost(imageName, MasterConfig.Server.Ip) if exits { imageNodes = append(imageNodes, MasterConfig.Server.Ip) } for ip, _ := range Gres { exits, _ := searchImageOnHost(imageName, ip) if exits { imageNodes = append(imageNodes, ip) } } if len(imageNodes) == 0 { return errors.New("You do not have the image in the system") } for ip, _ := range Ares { if *FlagDebug { util.PrintErr("search imageNodes on ip(imageName,ip):", imageName, ip) } exits, _ := searchImageOnHost(imageName, ip) if !exits { //no such image emptyNodes = append(emptyNodes, ip) } } transportHeads := partition(imageNodes, emptyNodes, imageName) //transport var chs []chan error setnum := len(transportHeads) if *FlagDebug { data, _ := json.Marshal(transportHeads) util.PrintErr(setnum, "transportHead:\n ", string(data)) } chs = make([]chan error, setnum) for i := 0; i < setnum; i++ { chs[i] = make(chan error) go saveTransLoadDel(imageName, transportHeads[i], chs[i]) } for i := 0; i < setnum; i++ { value := <-chs[i] if value != nil { return value } } if *FlagDebug { util.PrintErr("[ ImageTransport end!]") } return 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()) } }
// Runs the subcommand's runnable. If there is no subcommand // registered, it silently returns. // The params is passed to the subcommand by global var args func Run() { if matchingCmd != nil { if *flagHelp { subcommandUsage(matchingCmd) return } res, err := matchingCmd.command.Run(args) if err != nil { util.PrintErr("Server Error!") return } subCmdName := matchingCmd.name var output util.HttpResponse jsonerr := json.Unmarshal(res, &output) if jsonerr != nil { util.PrintErr("Error: Run()--json unmarshal err for output") return } //the data is return by the server correctly. switch subCmdName { case "create": if strings.HasPrefix(output.Status, "200") { fmt.Println(`Task "`, output.Warnings[0], `"`, "is created!") return } else { util.PrintErr(`Error: Task Created failed. `, output.Warnings[0]) } case "ps": if strings.HasPrefix(output.Status, "200") { fmt.Fprintf(os.Stdout, "%-20s%-30s%-20s%-20s%-20s%-20s\n", "Taskname", "Status", "Image", "Type", "Size", "CPUs") result := output.Warnings var psIterm server.PsOutput for iterm := range result { err := json.Unmarshal([]byte(result[iterm]), &psIterm) if err != nil { util.PrintErr("The result can not be parsed!") } dotindex := strings.Index(psIterm.Status, ".") if dotindex != -1 { psIterm.Status = psIterm.Status[:dotindex] + "s" } fmt.Fprintf(os.Stdout, "%-20s%-30s%-20s%-20s%-20s%-20s\n", psIterm.TaskName, psIterm.Status, psIterm.Image, psIterm.Type, strconv.Itoa(psIterm.Size), strconv.Itoa(psIterm.Cpus)) } } else { util.PrintErr(`Error: Task ps failed. `, output.Warnings[0]) } case "inspect": if strings.HasPrefix(output.Status, "200") { var outputByte []byte outputByte = []byte(output.Warnings[0]) _, exists := sendflags["f"] //such as .state.pid if !exists { //no field is provided var outputData server.InspectOutput err = json.Unmarshal(outputByte, &outputData) if err != nil { util.PrintErr("Error: the data from the server can not be resolved.") } util.FmtJson(outputByte) } else { fmt.Fprintf(os.Stdout, string(outputByte)) } } else { util.PrintErr(`Error: Task inspect failed. `, output.Warnings[0]) } case "stop": outputByte := []byte(output.Warnings[0]) var outputData server.StopOutput err = json.Unmarshal(outputByte, &outputData) if err != nil { util.PrintErr(string(outputByte)) } if strings.HasPrefix(output.Status, "200") { fmt.Println(outputData.Warning) } else { fmt.Println(outputData.String()) } case "start": outputByte := []byte(output.Warnings[0]) var outputData server.StartOutput err = json.Unmarshal(outputByte, &outputData) if err != nil { util.PrintErr(string(outputByte)) } if strings.HasPrefix(output.Status, "200") { fmt.Println(outputData.Warning) } else { fmt.Println(outputData.String()) } case "rm": outputByte := []byte(output.Warnings[0]) var outputData server.StartOutput err = json.Unmarshal(outputByte, &outputData) if err != nil { util.PrintErr(string(outputByte)) } if strings.HasPrefix(output.Status, "200") { fmt.Println(outputData.Warning) } else { fmt.Println(outputData.String()) } default: util.PrintErr("subcommand", subCmdName, "is not recognized!") } } }