-
Notifications
You must be signed in to change notification settings - Fork 77
Submit job with upload user's package #128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
0a0c5f0
e99aced
a82a645
e6be893
2fd0f98
a9521e6
add7f0d
5a63fe3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| package paddlecloud | ||
|
|
||
| import ( | ||
| "context" | ||
| "encoding/json" | ||
| "errors" | ||
| "flag" | ||
| "fmt" | ||
| "io" | ||
| "net/url" | ||
| "os" | ||
| "path" | ||
|
|
||
| "github.com/google/subcommands" | ||
| ) | ||
|
|
||
| // SimpleFileCmd define the subcommand of simple file operations. | ||
| type SimpleFileCmd struct { | ||
| } | ||
|
|
||
| // Name is subcommands name. | ||
| func (*SimpleFileCmd) Name() string { return "file" } | ||
|
|
||
| // Synopsis is subcommands synopsis. | ||
| func (*SimpleFileCmd) Synopsis() string { return "Simple file operations." } | ||
|
|
||
| // Usage is subcommands Usage. | ||
| func (*SimpleFileCmd) Usage() string { | ||
| return `file [put|get] <src> <dst>: | ||
| Options: | ||
| ` | ||
| } | ||
|
|
||
| // SetFlags registers subcommands flags. | ||
| func (p *SimpleFileCmd) SetFlags(f *flag.FlagSet) { | ||
| } | ||
|
|
||
| // Execute file ops. | ||
| func (p *SimpleFileCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { | ||
| if f.NArg() < 1 || f.NArg() > 3 { | ||
| f.Usage() | ||
| return subcommands.ExitFailure | ||
| } | ||
| switch f.Arg(0) { | ||
| case "put": | ||
| err := putFile(f.Arg(1), f.Arg(2)) | ||
| if err != nil { | ||
| fmt.Fprintf(os.Stderr, "put file error: %s\n", err) | ||
| return subcommands.ExitFailure | ||
| } | ||
| case "get": | ||
| err := getFile(f.Arg(1), f.Arg(2)) | ||
| if err != nil { | ||
| fmt.Fprintf(os.Stderr, "get file error: %s\n", err) | ||
| return subcommands.ExitFailure | ||
| } | ||
| default: | ||
| f.Usage() | ||
| return subcommands.ExitFailure | ||
| } | ||
| return subcommands.ExitSuccess | ||
| } | ||
|
|
||
| func putFile(src string, dest string) error { | ||
| query := url.Values{} | ||
| _, srcFile := path.Split(src) | ||
| destDir, destFile := path.Split(dest) | ||
| var destFullPath string | ||
| if len(destFile) == 0 { | ||
| destFullPath = path.Join(destDir, srcFile) | ||
| } else { | ||
| destFullPath = dest | ||
| } | ||
| query.Set("path", destFullPath) | ||
| respStr, err := PostFile(config.ActiveConfig.Endpoint+"/api/v1/file/", src, query) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| var respObj interface{} | ||
| if err = json.Unmarshal(respStr, &respObj); err != nil { | ||
| return err | ||
| } | ||
| // FIXME: Print an error if error message is not empty. Use response code instead | ||
| errMsg := respObj.(map[string]interface{})["msg"].(string) | ||
| if len(errMsg) > 0 { | ||
| fmt.Fprintf(os.Stderr, "upload file error: %s\n", errMsg) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Return an error?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. return error will break the filepath.Walk call. Will fix this after the above issue is done. |
||
| } | ||
| return nil | ||
| } | ||
|
|
||
| func getFile(src string, dest string) error { | ||
| query := url.Values{} | ||
| query.Set("path", src) | ||
| req, err := makeRequestToken(config.ActiveConfig.Endpoint+"/api/v1/file/", "GET", nil, "", query) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| resp, err := httpClient.Do(req) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| defer resp.Body.Close() | ||
| if resp.Status != HTTPOK { | ||
| return errors.New("server error: " + resp.Status) | ||
| } | ||
| _, srcFile := path.Split(src) | ||
| destDir, destFile := path.Split(dest) | ||
| var destFullPath string | ||
| if len(destFile) == 0 { | ||
| destFullPath = path.Join(destDir, srcFile) | ||
| } else { | ||
| destFullPath = dest | ||
| } | ||
| if _, err = os.Stat(destFullPath); err == nil { | ||
| return errors.New("file already exist: " + destFullPath) | ||
| } | ||
| out, err := os.Create(destFullPath) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| defer out.Close() | ||
| _, err = io.Copy(out, resp.Body) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| return nil | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,16 +3,18 @@ package paddlecloud | |
| import ( | ||
| "context" | ||
| "encoding/json" | ||
| "errors" | ||
| "flag" | ||
| "fmt" | ||
| "os" | ||
| "path" | ||
| "path/filepath" | ||
|
|
||
| "github.com/golang/glog" | ||
| "github.com/google/subcommands" | ||
| ) | ||
|
|
||
| // SubmitCmd define the subcommand of submitting paddle training jobs | ||
| // SubmitCmd define the subcommand of submitting paddle training jobs. | ||
| type SubmitCmd struct { | ||
| Jobname string `json:"name"` | ||
| Jobpackage string `json:"jobPackage"` | ||
|
|
@@ -29,21 +31,21 @@ type SubmitCmd struct { | |
| Passes int `json:"passes"` | ||
| } | ||
|
|
||
| // Name is subcommands name | ||
| // Name is subcommands name. | ||
| func (*SubmitCmd) Name() string { return "submit" } | ||
|
|
||
| // Synopsis is subcommands synopsis | ||
| // Synopsis is subcommands synopsis. | ||
| func (*SubmitCmd) Synopsis() string { return "Submit job to PaddlePaddle Cloud." } | ||
|
|
||
| // Usage is subcommands Usage | ||
| // Usage is subcommands Usage. | ||
| func (*SubmitCmd) Usage() string { | ||
| return `submit [options] <package path>: | ||
| Submit job to PaddlePaddle Cloud. | ||
| Options: | ||
| ` | ||
| } | ||
|
|
||
| // SetFlags registers subcommands flags | ||
| // SetFlags registers subcommands flags. | ||
| func (p *SubmitCmd) SetFlags(f *flag.FlagSet) { | ||
| f.StringVar(&p.Jobname, "jobname", "paddle-cluster-job", "Cluster job name.") | ||
| f.IntVar(&p.Parallelism, "parallelism", 1, "Number of parrallel trainers. Defaults to 1.") | ||
|
|
@@ -53,18 +55,18 @@ func (p *SubmitCmd) SetFlags(f *flag.FlagSet) { | |
| f.IntVar(&p.Pservers, "pservers", 0, "Number of parameter servers. Defaults equal to -p") | ||
| f.IntVar(&p.PSCPU, "pscpu", 1, "Parameter server CPU resource. Defaults to 1.") | ||
| f.StringVar(&p.PSMemory, "psmemory", "1Gi", "Parameter server momory resource. Defaults to 1Gi.") | ||
| f.StringVar(&p.Entry, "entry", "paddle train", "Command of starting trainer process. Defaults to paddle train") | ||
| f.StringVar(&p.Entry, "entry", "", "Command of starting trainer process. Defaults to paddle train") | ||
| f.StringVar(&p.Topology, "topology", "", "Will Be Deprecated .py file contains paddle v1 job configs") | ||
| f.IntVar(&p.Passes, "passes", 1, "Pass count for training job") | ||
| } | ||
|
|
||
| // Execute submit command | ||
| // Execute submit command. | ||
| func (p *SubmitCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { | ||
| if f.NArg() != 1 { | ||
| f.Usage() | ||
| return subcommands.ExitFailure | ||
| } | ||
| // default pservers count equals to trainers count | ||
| // default pservers count equals to trainers count. | ||
| if p.Pservers == 0 { | ||
| p.Pservers = p.Parallelism | ||
| } | ||
|
|
@@ -81,32 +83,50 @@ func (p *SubmitCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{} | |
| return subcommands.ExitSuccess | ||
| } | ||
|
|
||
| // Submitter submit job to cloud | ||
| // Submitter submit job to cloud. | ||
| type Submitter struct { | ||
| args *SubmitCmd | ||
| } | ||
|
|
||
| // NewSubmitter returns a submitter object | ||
| // NewSubmitter returns a submitter object. | ||
| func NewSubmitter(cmd *SubmitCmd) *Submitter { | ||
| s := Submitter{cmd} | ||
| return &s | ||
| } | ||
|
|
||
| // Submit current job | ||
| // Submit current job. | ||
| func (s *Submitter) Submit(jobPackage string) error { | ||
| // 1. upload user job package to pfs | ||
| filepath.Walk(jobPackage, func(path string, info os.FileInfo, err error) error { | ||
| glog.V(10).Infof("Uploading %s...\n", path) | ||
| return nil | ||
| //return postFile(path, config.activeConfig.endpoint+"/api/v1/files") | ||
| err := filepath.Walk(jobPackage, func(filePath string, info os.FileInfo, err error) error { | ||
| if info.IsDir() { | ||
| return nil | ||
| } | ||
| glog.V(10).Infof("Uploading %s...\n", filePath) | ||
| dest := "/" + path.Join("pfs", config.ActiveConfig.Name, "home", config.ActiveConfig.Username, filePath) | ||
|
||
| fmt.Printf("uploading: %s...\n", filePath) | ||
| return putFile(filePath, dest) | ||
| }) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| // 2. call paddlecloud server to create kubernetes job | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment is not useful.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Talk offline. OK! |
||
| jsonString, err := json.Marshal(s.args) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| glog.V(10).Infof("Submitting job: %s to %s\n", jsonString, config.ActiveConfig.Endpoint+"/api/v1/jobs") | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to specify
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. REST APIs are currently all |
||
| respBody, err := PostCall(config.ActiveConfig.Endpoint+"/api/v1/jobs/", jsonString) | ||
| glog.V(10).Infof("got return body size: %d", len(respBody)) | ||
| return err | ||
| if err != nil { | ||
| return err | ||
| } | ||
| var respObj interface{} | ||
| if err = json.Unmarshal(respBody, &respObj); err != nil { | ||
| return err | ||
| } | ||
| // FIXME: Return an error if error message is not empty. Use response code instead | ||
| errMsg := respObj.(map[string]interface{})["msg"].(string) | ||
| if len(errMsg) > 0 { | ||
| return errors.New(errMsg) | ||
| } | ||
| return nil | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is
response code? Is it aTODO?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a enhancement to uniform the response json format, see this issue: #129