@@ -617,7 +617,8 @@ type GetTrainJobResult struct { | |||||
JobName string `json:"job_name"` | JobName string `json:"job_name"` | ||||
JobID int64 `json:"job_id"` | JobID int64 `json:"job_id"` | ||||
Description string `json:"job_desc"` | Description string `json:"job_desc"` | ||||
Status int `json:"status"` | |||||
IntStatus int `json:"status"` | |||||
Status string | |||||
LongCreateTime int64 `json:"create_time"` | LongCreateTime int64 `json:"create_time"` | ||||
CreateTime string | CreateTime string | ||||
Duration int64 `json:"duration"` //训练作业的运行时间,单位为毫秒 | Duration int64 `json:"duration"` //训练作业的运行时间,单位为毫秒 | ||||
@@ -666,6 +667,12 @@ type GetTrainJobLogFileNamesResult struct { | |||||
LogFileList []string `json:"log_file_list"` | LogFileList []string `json:"log_file_list"` | ||||
} | } | ||||
type TrainJobResult struct { | |||||
ErrorCode string `json:"error_code"` | |||||
ErrorMsg string `json:"error_msg"` | |||||
IsSuccess bool `json:"is_success"` | |||||
} | |||||
func Cloudbrains(opts *CloudbrainsOptions) ([]*Cloudbrain, int64, error) { | func Cloudbrains(opts *CloudbrainsOptions) ([]*Cloudbrain, int64, error) { | ||||
sess := x.NewSession() | sess := x.NewSession() | ||||
defer sess.Close() | defer sess.Close() | ||||
@@ -164,7 +164,7 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) error { | |||||
} | } | ||||
err = models.CreateCloudbrain(&models.Cloudbrain{ | err = models.CreateCloudbrain(&models.Cloudbrain{ | ||||
Status: transTrainJobStatus(jobResult.Status), | |||||
Status: TransTrainJobStatus(jobResult.Status), | |||||
UserID: ctx.User.ID, | UserID: ctx.User.ID, | ||||
RepoID: ctx.Repo.Repository.ID, | RepoID: ctx.Repo.Repository.ID, | ||||
JobID: strconv.FormatInt(jobResult.JobID, 10), | JobID: strconv.FormatInt(jobResult.JobID, 10), | ||||
@@ -183,7 +183,7 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) error { | |||||
return nil | return nil | ||||
} | } | ||||
func transTrainJobStatus(status int) string{ | |||||
func TransTrainJobStatus(status int) string{ | |||||
switch status { | switch status { | ||||
case 0: | case 0: | ||||
return "UNKNOWN" | return "UNKNOWN" | ||||
@@ -213,7 +213,7 @@ sendjob: | |||||
return &result, nil | return &result, nil | ||||
} | } | ||||
func DelJob(jobID string) (*models.NotebookDelResult, error) { | |||||
func DelNotebook(jobID string) (*models.NotebookDelResult, error) { | |||||
checkSetting() | checkSetting() | ||||
client := getRestyClient() | client := getRestyClient() | ||||
var result models.NotebookDelResult | var result models.NotebookDelResult | ||||
@@ -477,10 +477,9 @@ func GetTrainJob(jobID, versionID string) (*models.GetTrainJobResult, error) { | |||||
sendjob: | sendjob: | ||||
res, err := client.R(). | res, err := client.R(). | ||||
SetHeader("Content-Type", "application/json"). | |||||
SetAuthToken(TOKEN). | SetAuthToken(TOKEN). | ||||
SetResult(&result). | SetResult(&result). | ||||
Get(HOST + "/v1/" + setting.ProjectID + urlTrainJob + "/" + jobID + "/" + versionID) | |||||
Get(HOST + "/v1/" + setting.ProjectID + urlTrainJob + "/" + jobID + "/versions/" + versionID) | |||||
if err != nil { | if err != nil { | ||||
return nil, fmt.Errorf("resty GetTrainJob: %v", err) | return nil, fmt.Errorf("resty GetTrainJob: %v", err) | ||||
@@ -597,3 +596,44 @@ sendjob: | |||||
return &result, nil | return &result, nil | ||||
} | } | ||||
func DelTrainJob(jobID string) (*models.TrainJobResult, error) { | |||||
checkSetting() | |||||
client := getRestyClient() | |||||
var result models.TrainJobResult | |||||
retry := 0 | |||||
sendjob: | |||||
res, err := client.R(). | |||||
SetAuthToken(TOKEN). | |||||
SetResult(&result). | |||||
Delete(HOST + "/v1/" + setting.ProjectID + urlTrainJob + "/" + jobID) | |||||
if err != nil { | |||||
return &result, fmt.Errorf("resty DelTrainJob: %v", err) | |||||
} | |||||
if res.StatusCode() == http.StatusUnauthorized && retry < 1 { | |||||
retry++ | |||||
_ = getToken() | |||||
goto sendjob | |||||
} | |||||
if res.StatusCode() != http.StatusOK { | |||||
var temp models.ErrorResult | |||||
if err = json.Unmarshal([]byte(res.String()), &temp); err != nil { | |||||
log.Error("json.Unmarshal failed(%s): %v", res.String(), err.Error()) | |||||
return &result, fmt.Errorf("json.Unmarshal failed(%s): %v", res.String(), err.Error()) | |||||
} | |||||
log.Error("DelTrainJob failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg) | |||||
return &result, fmt.Errorf("DelTrainJob failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg) | |||||
} | |||||
if !result.IsSuccess { | |||||
log.Error("DelTrainJob(%s) failed", jobID) | |||||
return &result, fmt.Errorf("删除训练作业失败:%s", result.ErrorMsg) | |||||
} | |||||
return &result, nil | |||||
} |
@@ -239,7 +239,7 @@ func NotebookDel(ctx *context.Context) { | |||||
return | return | ||||
} | } | ||||
_, err = modelarts.DelJob(jobID) | |||||
_, err = modelarts.DelNotebook(jobID) | |||||
if err != nil { | if err != nil { | ||||
log.Error("DelJob(%s) failed:%v", task.JobName, err.Error()) | log.Error("DelJob(%s) failed:%v", task.JobName, err.Error()) | ||||
ctx.ServerError("DelJob failed", err) | ctx.ServerError("DelJob failed", err) | ||||
@@ -545,8 +545,8 @@ func TrainJobShow(ctx *context.Context) { | |||||
} | } | ||||
if result != nil { | if result != nil { | ||||
createTime, _ := com.StrTo(result.LongCreateTime).Int64() | |||||
result.CreateTime = time.Unix(int64(createTime/1000), 0).Format("2006-01-02 15:04:05") | |||||
result.CreateTime = time.Unix(int64(result.LongCreateTime/1000), 0).Format("2006-01-02 15:04:05") | |||||
result.Status = modelarts.TransTrainJobStatus(result.IntStatus) | |||||
} | } | ||||
ctx.Data["task"] = task | ctx.Data["task"] = task | ||||
@@ -583,3 +583,27 @@ func TrainJobGetLog(ctx *context.Context) { | |||||
ctx.Data["log"] = result | ctx.Data["log"] = result | ||||
ctx.HTML(http.StatusOK, tplModelArtsTrainJobShow) | ctx.HTML(http.StatusOK, tplModelArtsTrainJobShow) | ||||
} | } | ||||
func TrainJobDel(ctx *context.Context) { | |||||
var jobID = ctx.Params(":jobid") | |||||
task, err := models.GetCloudbrainByJobID(jobID) | |||||
if err != nil { | |||||
ctx.ServerError("GetCloudbrainByJobID failed", err) | |||||
return | |||||
} | |||||
_, err = modelarts.DelTrainJob(jobID) | |||||
if err != nil { | |||||
log.Error("TrainJobDel(%s) failed:%v", task.JobName, err.Error()) | |||||
ctx.ServerError("TrainJobDel failed", err) | |||||
return | |||||
} | |||||
err = models.DeleteJob(task) | |||||
if err != nil { | |||||
ctx.ServerError("TrainJobDel failed", err) | |||||
return | |||||
} | |||||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job") | |||||
} |
@@ -935,7 +935,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
m.Get("", reqRepoCloudBrainReader, repo.TrainJobShow) | m.Get("", reqRepoCloudBrainReader, repo.TrainJobShow) | ||||
m.Get("/debug", reqRepoCloudBrainReader, repo.NotebookDebug) | m.Get("/debug", reqRepoCloudBrainReader, repo.NotebookDebug) | ||||
m.Post("/stop", reqRepoCloudBrainWriter, repo.NotebookStop) | m.Post("/stop", reqRepoCloudBrainWriter, repo.NotebookStop) | ||||
m.Post("/del", reqRepoCloudBrainWriter, repo.NotebookDel) | |||||
m.Post("/del", reqRepoCloudBrainWriter, repo.TrainJobDel) | |||||
m.Get("/log", reqRepoCloudBrainReader, repo.TrainJobGetLog) | m.Get("/log", reqRepoCloudBrainReader, repo.TrainJobGetLog) | ||||
}) | }) | ||||
m.Get("/create", reqRepoCloudBrainWriter, repo.TrainJobNew) | m.Get("/create", reqRepoCloudBrainWriter, repo.TrainJobNew) | ||||
@@ -1,5 +1,10 @@ | |||||
{{template "base/head" .}} | {{template "base/head" .}} | ||||
<style> | <style> | ||||
#deletemodel { | |||||
width: 100%; | |||||
height: 100%; | |||||
} | |||||
.ui.segment.bottom.attached { | .ui.segment.bottom.attached { | ||||
border: none; | border: none; | ||||
} | } | ||||
@@ -94,9 +99,9 @@ | |||||
<!-- 删除 --> | <!-- 删除 --> | ||||
<div class="one wide column"> | <div class="one wide column"> | ||||
<div class="ui text center clipboard"> | <div class="ui text center clipboard"> | ||||
<form id="delForm-{{.JobID}}" action="{{if ne .Status "STOPPED"}}javascript:void(0){{else}}{{$.Link}}/{{.JobID}}/del{{end}}" method="post"> | |||||
<form id="delForm-{{.JobID}}" action="{{$.Link}}/{{.JobID}}/del" method="post"> | |||||
{{$.CsrfTokenHtml}} | {{$.CsrfTokenHtml}} | ||||
<a class="fitted" onclick="assertDelete(this)" style="{{if ne .Status "STOPPED"}}color:#CCCCCC{{end}}; font-size:16px; font-weight:bold">删除</a> | |||||
<a class="fitted" onclick="assertDelete(this)" style="font-size:16px; font-weight:bold">删除</a> | |||||
</form> | </form> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -128,4 +133,32 @@ | |||||
$(this).siblings().removeClass("activate") | $(this).siblings().removeClass("activate") | ||||
$(this).addClass("activate") | $(this).addClass("activate") | ||||
}) | }) | ||||
</script>{{template "base/head" .}} | |||||
// 删除时用户确认 | |||||
function assertDelete(obj) { | |||||
if (obj.style.color == "rgb(204, 204, 204)") { | |||||
return | |||||
} else { | |||||
var delId = obj.parentNode.id | |||||
flag = 1; | |||||
$('.ui.basic.modal') | |||||
.modal({ | |||||
onDeny: function() { | |||||
flag = false | |||||
}, | |||||
onApprove: function() { | |||||
document.getElementById(delId).submit() | |||||
flag = true | |||||
}, | |||||
onHidden: function() { | |||||
if (flag == false) { | |||||
$('.alert').html('您已取消操作').removeClass('alert-success').addClass('alert-danger').show().delay(1500).fadeOut(); | |||||
} | |||||
} | |||||
}) | |||||
.modal('show') | |||||
} | |||||
} | |||||
</script> | |||||
{{template "base/head" .}} |
@@ -33,27 +33,27 @@ | |||||
<tbody> | <tbody> | ||||
<tr> | <tr> | ||||
<td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.job_name"}} </td> | <td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.job_name"}} </td> | ||||
<td>{{.Profile.DeType}}</td> | |||||
<td>{{.result.JobName}}</td> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.job_status"}} </td> | <td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.job_status"}} </td> | ||||
<td>{{.Profile.DeType}}</td> | |||||
<td>{{.result.Status}}</td> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.version"}} </td> | <td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.version"}} </td> | ||||
<td>{{.Profile.FlavorType}}</td> | |||||
<td>{{.result.VersionName}}</td> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.start_time"}} </td> | <td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.start_time"}} </td> | ||||
<td>{{.Profile.FlavorType}}</td> | |||||
<td>{{.result.CreateTime}}</td> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.dura_time"}} </td> | <td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.dura_time"}} </td> | ||||
<td>{{.Profile.DeType}}</td> | |||||
<td>{{.result.Duration}}</td> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.description"}} </td> | <td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.description"}} </td> | ||||
<td>{{.Profile.FlavorType}}</td> | |||||
<td>{{.result.Description}}</td> | |||||
</tr> | </tr> | ||||
</tbody> | </tbody> | ||||
</table> | </table> | ||||
@@ -66,19 +66,19 @@ | |||||
<tbody> | <tbody> | ||||
<tr> | <tr> | ||||
<td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.AI_driver"}} </td> | <td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.AI_driver"}} </td> | ||||
<td>{{.Profile.DeType}}</td> | |||||
<td>{{.result.BootFileUrl}}</td> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.start_file"}}</td> | <td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.start_file"}}</td> | ||||
<td>{{.Profile.DeType}}</td> | |||||
<td>{{.result.BootFileUrl}}</td> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.dataset"}} </td> | <td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.dataset"}} </td> | ||||
<td>{{.Profile.FlavorType}}</td> | |||||
<td>{{.result.BootFileUrl}}</td> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.run_parameter"}} </td> | <td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.run_parameter"}} </td> | ||||
<td>{{.Profile.FlavorType}}</td> | |||||
<td>{{.result.Parameter}}</td> | |||||
</tr> | </tr> | ||||
</tbody> | </tbody> | ||||
</table> | </table> | ||||
@@ -91,15 +91,15 @@ | |||||
<tbody> | <tbody> | ||||
<tr> | <tr> | ||||
<td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.resource_pool"}} </td> | <td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.resource_pool"}} </td> | ||||
<td>{{.Profile.DeType}}</td> | |||||
<td>{{.result.PoolName}}</td> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.amount_of_compute_node"}}</td> | <td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.amount_of_compute_node"}}</td> | ||||
<td>{{.Profile.DeType}}</td> | |||||
<td>{{.result.WorkServerNum}}</td> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.NAS_mount_path"}} </td> | <td class="four wide"> {{.i18n.Tr "repo.modelarts.train_job.NAS_mount_path"}} </td> | ||||
<td>{{.Profile.FlavorType}}</td> | |||||
<td>{{.result.NasMountPath}}</td> | |||||
</tr> | </tr> | ||||
</tbody> | </tbody> | ||||
</table> | </table> | ||||