Skip to content
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

Submit job with upload user's package #128

Merged
merged 8 commits into from
Jun 7, 2017

Conversation

typhoonzero
Copy link
Collaborator

Fix #127

@typhoonzero typhoonzero changed the title Simple file Submit job with upload user's package Jun 6, 2017
"github.com/google/subcommands"
)

// SimpleFileCmd define the subcommand of simple file operations
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment should be a sentence, which ends with ".".

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

bodyBuf := &bytes.Buffer{}
bodyWriter := multipart.NewWriter(bodyBuf)

// this step is very important
fileWriter, err := bodyWriter.CreateFormFile("uploadfile", filename)
fileWriter, err := bodyWriter.CreateFormFile("file", filename)
if err != nil {
fmt.Fprintf(os.Stderr, "error writing to buffer: %v\n", err)
return []byte{}, err
}

// open file handle
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment maybe not useful.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -124,7 +124,7 @@ func PostFile(targetURL string, filename string) ([]byte, error) {
contentType := bodyWriter.FormDataContentType()
bodyWriter.Close()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to check the return of Close().

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

if err = json.Unmarshal(respStr, &respObj); err != nil {
return err
}
// FIXME: Print an error if error message is not empty. Use response code instead
Copy link
Collaborator

@gongweibao gongweibao Jun 7, 2017

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 a TODO?

Copy link
Collaborator Author

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

// 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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return an error?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The 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.

})
if err != nil {
return err
}
// 2. call paddlecloud server to create kubernetes job
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is not useful.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Talk offline. OK!

})
if err != nil {
return err
}
// 2. call paddlecloud server to create kubernetes job
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")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to specify /api/v1/jobs to be constant?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

REST APIs are currently all v1, change this when we have v2


def post(self, request, format=None):
"""
Simple up file
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

up=>upload

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to get and put

data = file_obj.read(4096)
if not data:
break
fn.write(data)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check errors may occur.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Django will catch exceptions and return a default response.


def get(self, request, format=None):
"""
Simple down file
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

down=>download

Copy link
Collaborator Author

@typhoonzero typhoonzero Jun 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to get and put


def __validate_path(self, request, file_path):
"""
returns error_msg. error_msg will be empty if there's no error
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A sentence should end with '.'.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

return nil
}
glog.V(10).Infof("Uploading %s...\n", filePath)
dest := "/" + path.Join("pfs", config.ActiveConfig.Name, "home", config.ActiveConfig.Username, filePath)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dest := "/" + path.Join("pfs", config.ActiveConfig.Name, ...
==>
dest := path.Join("/pfs", config.ActiveConfig.Name, ...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool. Done.

@@ -89,6 +91,23 @@ def post(self, request, format=None):
# get user specified image
job_image = obj.get("image", None)
gpu_count = obj.get("gpu", 0)
# jobPackage validation: startwith /pfs
# NOTE: always overwrite the job package when the directory exists
job_package =obj.get("jobPackage", "")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this logic, users will use the parameter jobPackage as /pfs/xxx/home/yyy or /xxxx or a relative path, there is so much format for the jobPackage, it looks so much confusing, maybe we can only support one format, such as "/pfs/$dc/home/$username", I think it's more clearly.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a brief discussion, we decide to use "jobname" as default path to store the package content. So that users can find history package and program file folders if they want to find out something.

@@ -140,7 +159,7 @@ def post(self, request, format=None):
except ApiException, e:
logging.error("error submitting trainer job: %s" % e)
return utils.simple_response(500, str(e))
return utils.simple_response(200, "OK")
return utils.simple_response(200, "")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this change is not necessary.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed paddlecloud client to check if msg is not empty, means there is some error.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I got it and make a mark for using HTTP status instead of check msg.

Yancey1989
Yancey1989 previously approved these changes Jun 7, 2017
Copy link
Collaborator

@Yancey1989 Yancey1989 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Copy link
Collaborator

@gongweibao gongweibao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@typhoonzero typhoonzero merged commit 522d8eb into PaddlePaddle:develop Jun 7, 2017
@typhoonzero typhoonzero deleted the simple_file branch November 2, 2017 10:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants