@@ -2,7 +2,6 @@ package models | |||
import ( | |||
"encoding/json" | |||
"errors" | |||
"fmt" | |||
"time" | |||
"xorm.io/xorm" | |||
@@ -300,7 +299,7 @@ type CommitImageResult struct { | |||
Payload map[string]interface{} `json:"payload"` | |||
} | |||
type StopJobResult struct { | |||
type CloudBrainResult struct { | |||
Code string `json:"code"` | |||
Msg string `json:"msg"` | |||
} | |||
@@ -569,7 +568,7 @@ func getRepoCloudBrain(cb *Cloudbrain) (*Cloudbrain, error) { | |||
if err != nil { | |||
return nil, err | |||
} else if !has { | |||
return nil, errors.New("cloudbrain task is not found") | |||
return nil, ErrJobNotExist{} | |||
} | |||
return cb, nil | |||
} | |||
@@ -609,3 +608,8 @@ func deleteJob(e Engine, job *Cloudbrain) error { | |||
_, err := e.ID(job.ID).Delete(job) | |||
return err | |||
} | |||
func GetCloudbrainByName(jobName string) (*Cloudbrain, error) { | |||
cb := &Cloudbrain{JobName: jobName} | |||
return getRepoCloudBrain(cb) | |||
} |
@@ -1987,3 +1987,15 @@ func IsErrFileChunkNotExist(err error) bool { | |||
_, ok := err.(ErrFileChunkNotExist) | |||
return ok | |||
} | |||
type ErrJobNotExist struct { | |||
} | |||
func IsErrJobNotExist(err error) bool { | |||
_, ok := err.(ErrJobNotExist) | |||
return ok | |||
} | |||
func (err ErrJobNotExist) Error() string { | |||
return fmt.Sprintf("the job does not exist") | |||
} |
@@ -2,6 +2,7 @@ package cloudbrain | |||
import ( | |||
"code.gitea.io/gitea/modules/log" | |||
"encoding/json" | |||
"fmt" | |||
"code.gitea.io/gitea/models" | |||
@@ -143,14 +144,26 @@ sendjob: | |||
return nil, fmt.Errorf("resty GetImages: %v", err) | |||
} | |||
if getImagesResult.Code == "S401" && retry < 1 { | |||
var response models.CloudBrainResult | |||
err = json.Unmarshal(res.Body(), &response) | |||
if err != nil { | |||
log.Error("json.Unmarshal failed: %s", err.Error()) | |||
return &getImagesResult, fmt.Errorf("json.Unmarshal failed: %s", err.Error()) | |||
} | |||
if response.Code == "S401" && retry < 1 { | |||
retry++ | |||
_ = loginCloudbrain() | |||
goto sendjob | |||
} | |||
if len(response.Code) != 0 { | |||
log.Error("getImagesResult failed(%s): %s", response.Code, response.Msg) | |||
return &getImagesResult, fmt.Errorf("getImagesResult failed(%s): %s", response.Code, response.Msg) | |||
} | |||
if getImagesResult.Code != Success { | |||
return &getImagesResult, fmt.Errorf("getImgesResult err: %s", res.String()) | |||
return &getImagesResult, fmt.Errorf("getImagesResult err: %s", res.String()) | |||
} | |||
return &getImagesResult, nil | |||
@@ -223,7 +236,7 @@ sendjob: | |||
func StopJob(jobID string) error { | |||
checkSetting() | |||
client := getRestyClient() | |||
var result models.StopJobResult | |||
var result models.CloudBrainResult | |||
retry := 0 | |||
@@ -67,19 +67,43 @@ func (l *Logger) Log(skip int, level Level, format string, v ...interface{}) err | |||
caller = fn.Name() + "()" | |||
} | |||
} | |||
msg := format | |||
if len(v) > 0 { | |||
msg = ColorSprintf(format, v...) | |||
} | |||
stack := "" | |||
if l.GetStacktraceLevel() <= level { | |||
stack = Stack(skip + 1) | |||
} | |||
return l.SendLog(level, caller, strings.TrimPrefix(filename, prefix), line, msg, stack) | |||
msg := format | |||
if len(v) > 0 { | |||
switch v[len(v)-1].(type) { | |||
case string: | |||
if !strings.Contains(v[len(v)-1].(string), "-") { | |||
//has no msgID | |||
msg = ColorSprintf(format, v...) | |||
return l.SendLog(level, caller, strings.TrimPrefix(filename, prefix), line, msg, "", stack) | |||
} else { | |||
if len(v) > 1 { | |||
args := make([]interface{}, len(v)-1) | |||
for i := 0; i < len(v)-1; i++ { | |||
args[i] = v[i] | |||
} | |||
msg = ColorSprintf(format, args...) | |||
} | |||
return l.SendLog(level, caller, strings.TrimPrefix(filename, prefix), line, msg, v[len(v)-1].(string), stack) | |||
} | |||
default: | |||
//has no msgID | |||
msg = ColorSprintf(format, v...) | |||
return l.SendLog(level, caller, strings.TrimPrefix(filename, prefix), line, msg, "", stack) | |||
} | |||
} else { | |||
//has no msgID | |||
return l.SendLog(level, caller, strings.TrimPrefix(filename, prefix), line, msg, "", stack) | |||
} | |||
} | |||
// SendLog sends a log event at the provided level with the information given | |||
func (l *Logger) SendLog(level Level, caller, filename string, line int, msg string, stack string) error { | |||
func (l *Logger) SendLog(level Level, caller, filename string, line int, msg, msgID, stack string) error { | |||
if l.GetLevel() > level { | |||
return nil | |||
} | |||
@@ -88,7 +112,7 @@ func (l *Logger) SendLog(level Level, caller, filename string, line int, msg str | |||
caller: caller, | |||
filename: filename, | |||
line: line, | |||
msg: msg, | |||
msg: msg + "[" + msgID + "]", | |||
time: time.Now(), | |||
stacktrace: stack, | |||
} | |||
@@ -83,7 +83,7 @@ func (m *MinioStorage) PresignedGetURL(path string, fileName string) (string, er | |||
reqParams.Set("response-content-disposition", "attachment; filename=\""+fileName+"\"") | |||
var preURL *url.URL | |||
preURL, err := m.client.PresignedGetObject(m.bucket, m.buildMinioPath(path), PresignedGetUrlExpireTime, reqParams) | |||
preURL, err := m.client.PresignedGetObject(m.bucket, path, PresignedGetUrlExpireTime, reqParams) | |||
if err != nil { | |||
return "", err | |||
} | |||
@@ -1819,6 +1819,7 @@ org_full_name_holder=组织全名 | |||
org_name_helper=组织名字应该简单明了。 | |||
create_org=创建组织 | |||
repo_updated=最后更新于 | |||
home=组织主页 | |||
people=组织成员 | |||
teams=组织团队 | |||
lower_members=名成员 | |||
@@ -20,6 +20,7 @@ const ( | |||
// Home show organization home page | |||
func Home(ctx *context.Context) { | |||
ctx.SetParams(":org", ctx.Params(":username")) | |||
ctx.Data["PageIsOrgHome"] = true | |||
context.HandleOrgAssignment(ctx) | |||
if ctx.Written() { | |||
return | |||
@@ -205,7 +205,7 @@ func GetAttachment(ctx *context.Context) { | |||
if setting.Attachment.StoreType == storage.MinioStorageType { | |||
url := "" | |||
if typeCloudBrain == models.TypeCloudBrainOne { | |||
url, err = storage.Attachments.PresignedGetURL(attach.RelativePath(), attach.Name) | |||
url, err = storage.Attachments.PresignedGetURL(setting.Attachment.Minio.BasePath + attach.RelativePath(), attach.Name) | |||
if err != nil { | |||
ctx.ServerError("PresignedGetURL", err) | |||
return | |||
@@ -28,14 +28,14 @@ const ( | |||
func BlockChainIndex(ctx *context.Context) { | |||
repo := ctx.Repo.Repository | |||
if repo.ContractAddress == "" || ctx.User.PublicKey == "" { | |||
log.Error("the repo(%d) or the user(%d) has not been initialized in block_chain", repo.RepoID, ctx.User.ID) | |||
log.Error("the repo(%d) or the user(%d) has not been initialized in block_chain", repo.RepoID, ctx.User.ID, ctx.Data["msgID"]) | |||
ctx.HTML(http.StatusInternalServerError, tplBlockChainIndex) | |||
return | |||
} | |||
res, err := blockchain.GetBalance(repo.ContractAddress, ctx.User.PublicKey) | |||
if err != nil { | |||
log.Error("GetBalance(%s) failed:%v", ctx.User.PublicKey, err) | |||
log.Error("GetBalance(%s) failed:%s", ctx.User.PublicKey, err, ctx.Data["msgID"]) | |||
ctx.HTML(http.StatusInternalServerError, tplBlockChainIndex) | |||
return | |||
} | |||
@@ -52,7 +52,7 @@ func HandleBlockChainInitNotify(ctx *context.Context) { | |||
repo, err := models.GetRepositoryByID(req.RepoId) | |||
if err != nil { | |||
log.Error("GetRepositoryByID failed:", err.Error()) | |||
log.Error("GetRepositoryByID failed:%v", err.Error(), ctx.Data["msgID"]) | |||
ctx.JSON(200, map[string]string{ | |||
"code": "-1", | |||
"message": "internal error", | |||
@@ -61,7 +61,7 @@ func HandleBlockChainInitNotify(ctx *context.Context) { | |||
} | |||
if repo.BlockChainStatus == models.RepoBlockChainSuccess && len(repo.ContractAddress) != 0 { | |||
log.Error("the repo has been RepoBlockChainSuccess:", req.RepoId) | |||
log.Error("the repo has been RepoBlockChainSuccess:%d", req.RepoId, ctx.Data["msgID"]) | |||
ctx.JSON(200, map[string]string{ | |||
"code": "-1", | |||
"message": "the repo has been RepoBlockChainSuccess", | |||
@@ -73,7 +73,7 @@ func HandleBlockChainInitNotify(ctx *context.Context) { | |||
repo.ContractAddress = req.ContractAddress | |||
if err = models.UpdateRepositoryCols(repo, "block_chain_status", "contract_address"); err != nil { | |||
log.Error("UpdateRepositoryCols failed:", err.Error()) | |||
log.Error("UpdateRepositoryCols failed:%v", err.Error(), ctx.Data["msgID"]) | |||
ctx.JSON(200, map[string]string{ | |||
"code": "-1", | |||
"message": "internal error", | |||
@@ -91,7 +91,7 @@ func HandleBlockChainCommitNotify(ctx *context.Context) { | |||
var req BlockChainCommitNotify | |||
data, _ := ctx.Req.Body().Bytes() | |||
if err := json.Unmarshal(data, &req); err != nil { | |||
log.Error("json.Unmarshal failed:", err.Error()) | |||
log.Error("json.Unmarshal failed:%v", err.Error(), ctx.Data["msgID"]) | |||
ctx.JSON(200, map[string]string{ | |||
"code": "-1", | |||
"message": "response data error", | |||
@@ -101,7 +101,7 @@ func HandleBlockChainCommitNotify(ctx *context.Context) { | |||
blockChain, err := models.GetBlockChainByCommitID(req.CommitID) | |||
if err != nil { | |||
log.Error("GetRepositoryByID failed:", err.Error()) | |||
log.Error("GetRepositoryByID failed:%v", err.Error(), ctx.Data["msgID"]) | |||
ctx.JSON(200, map[string]string{ | |||
"code": "-1", | |||
"message": "internal error", | |||
@@ -110,7 +110,7 @@ func HandleBlockChainCommitNotify(ctx *context.Context) { | |||
} | |||
if blockChain.Status == models.BlockChainCommitSuccess { | |||
log.Error("the commit has been BlockChainCommitReady:", blockChain.RepoID) | |||
log.Error("the commit has been BlockChainCommitReady:%s", blockChain.RepoID, ctx.Data["msgID"]) | |||
ctx.JSON(200, map[string]string{ | |||
"code": "-1", | |||
"message": "the commit has been BlockChainCommitReady", | |||
@@ -122,7 +122,7 @@ func HandleBlockChainCommitNotify(ctx *context.Context) { | |||
blockChain.TransactionHash = req.TransactionHash | |||
if err = models.UpdateBlockChainCols(blockChain, "status", "transaction_hash"); err != nil { | |||
log.Error("UpdateBlockChainCols failed:", err.Error()) | |||
log.Error("UpdateBlockChainCols failed:%v", err.Error(), ctx.Data["msgID"]) | |||
ctx.JSON(200, map[string]string{ | |||
"code": "-1", | |||
"message": "internal error", | |||
@@ -2,8 +2,10 @@ package repo | |||
import ( | |||
"code.gitea.io/gitea/modules/git" | |||
"code.gitea.io/gitea/modules/storage" | |||
"encoding/json" | |||
"errors" | |||
"net/http" | |||
"os" | |||
"os/exec" | |||
"strconv" | |||
@@ -23,6 +25,7 @@ const ( | |||
tplCloudBrainIndex base.TplName = "repo/cloudbrain/index" | |||
tplCloudBrainNew base.TplName = "repo/cloudbrain/new" | |||
tplCloudBrainShow base.TplName = "repo/cloudbrain/show" | |||
tplCloudBrainShowModels base.TplName = "repo/cloudbrain/models/index" | |||
) | |||
var ( | |||
@@ -93,7 +96,7 @@ func CloudBrainNew(ctx *context.Context) { | |||
result, err := cloudbrain.GetImages() | |||
if err != nil { | |||
ctx.Data["error"] = err.Error() | |||
log.Error("cloudbrain.GetImages failed:", err.Error()) | |||
log.Error("cloudbrain.GetImages failed:", err.Error(), ctx.Data["msgID"]) | |||
} | |||
for i, payload := range result.Payload.ImageInfo { | |||
@@ -109,7 +112,7 @@ func CloudBrainNew(ctx *context.Context) { | |||
resultPublic, err := cloudbrain.GetPublicImages() | |||
if err != nil { | |||
ctx.Data["error"] = err.Error() | |||
log.Error("cloudbrain.GetPublicImages failed:", err.Error()) | |||
log.Error("cloudbrain.GetPublicImages failed:", err.Error(), ctx.Data["msgID"]) | |||
} | |||
for i, payload := range resultPublic.Payload.ImageInfo { | |||
@@ -161,15 +164,28 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
codePath := setting.JobPath + jobName + cloudbrain.CodeMountPath | |||
if jobType != string(models.JobTypeBenchmark) && jobType != string(models.JobTypeDebug) && jobType != string(models.JobTypeSnn4imagenet) { | |||
log.Error("jobtype error:", jobType) | |||
log.Error("jobtype error:", jobType, ctx.Data["msgID"]) | |||
ctx.RenderWithErr("jobtype error", tplCloudBrainNew, &form) | |||
return | |||
} | |||
_, err := models.GetCloudbrainByName(jobName) | |||
if err == nil { | |||
log.Error("the job name did already exist", ctx.Data["MsgID"]) | |||
ctx.RenderWithErr("the job name did already exist", tplCloudBrainNew, &form) | |||
return | |||
} else { | |||
if !models.IsErrJobNotExist(err) { | |||
log.Error("system error, %v", err, ctx.Data["MsgID"]) | |||
ctx.RenderWithErr("system error", tplCloudBrainNew, &form) | |||
return | |||
} | |||
} | |||
repo := ctx.Repo.Repository | |||
downloadCode(repo, codePath) | |||
modelPath := setting.JobPath + jobName + cloudbrain.ModelMountPath | |||
err := os.MkdirAll(modelPath, os.ModePerm) | |||
err = os.MkdirAll(modelPath, os.ModePerm) | |||
if err != nil { | |||
ctx.RenderWithErr(err.Error(), tplCloudBrainNew, &form) | |||
return | |||
@@ -264,7 +280,7 @@ func CloudBrainCommitImage(ctx *context.Context, form auth.CommitImageCloudBrain | |||
ImageTag: form.Tag, | |||
}) | |||
if err != nil { | |||
log.Error("CommitImage(%s) failed:", task.JobName, err.Error()) | |||
log.Error("CommitImage(%s) failed:%v", task.JobName, err.Error(), ctx.Data["msgID"]) | |||
ctx.JSON(200, map[string]string{ | |||
"result_code": "-1", | |||
"error_msg": "CommitImage failed", | |||
@@ -287,14 +303,14 @@ func CloudBrainStop(ctx *context.Context) { | |||
} | |||
if task.Status == string(models.JobStopped) { | |||
log.Error("the job(%s) has been stopped", task.JobName) | |||
log.Error("the job(%s) has been stopped", task.JobName, ctx.Data["msgID"]) | |||
ctx.ServerError("the job has been stopped", errors.New("the job has been stopped")) | |||
return | |||
} | |||
err = cloudbrain.StopJob(jobID) | |||
if err != nil { | |||
log.Error("StopJob(%s) failed:%v", task.JobName, err.Error()) | |||
log.Error("StopJob(%s) failed:%v", task.JobName, err.Error(), ctx.Data["msgID"]) | |||
ctx.ServerError("StopJob failed", err) | |||
return | |||
} | |||
@@ -318,7 +334,7 @@ func CloudBrainDel(ctx *context.Context) { | |||
} | |||
if task.Status != string(models.JobStopped) { | |||
log.Error("the job(%s) has not been stopped", task.JobName) | |||
log.Error("the job(%s) has not been stopped", task.JobName, ctx.Data["msgID"]) | |||
ctx.ServerError("the job has not been stopped", errors.New("the job has not been stopped")) | |||
return | |||
} | |||
@@ -332,6 +348,69 @@ func CloudBrainDel(ctx *context.Context) { | |||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/cloudbrain") | |||
} | |||
func CloudBrainShowModels(ctx *context.Context) { | |||
ctx.Data["PageIsCloudBrain"] = true | |||
jobID := ctx.Params(":jobid") | |||
parentDir := ctx.Query("parentDir") | |||
dirArray := strings.Split(parentDir, "/") | |||
task, err := models.GetCloudbrainByJobID(jobID) | |||
if err != nil { | |||
log.Error("no such job!", ctx.Data["msgID"]) | |||
ctx.ServerError("no such job:", err) | |||
return | |||
} | |||
//get dirs | |||
dirs, err := getModelDirs(task.JobName, parentDir) | |||
if err != nil { | |||
log.Error("getModelDirs failed:%v", err.Error(), ctx.Data["msgID"]) | |||
ctx.ServerError("getModelDirs failed:", err) | |||
return | |||
} | |||
var fileInfos []FileInfo | |||
err = json.Unmarshal([]byte(dirs), &fileInfos) | |||
if err != nil { | |||
log.Error("json.Unmarshal failed:%v", err.Error(), ctx.Data["msgID"]) | |||
ctx.ServerError("json.Unmarshal failed:", err) | |||
return | |||
} | |||
ctx.Data["Path"] = dirArray | |||
ctx.Data["Dirs"] = fileInfos | |||
ctx.Data["task"] = task | |||
ctx.Data["JobID"] = jobID | |||
ctx.HTML(200, tplCloudBrainShowModels) | |||
} | |||
func getModelDirs(jobName string, parentDir string) (string, error) { | |||
var req string | |||
modelActualPath := setting.JobPath + jobName + "/model/" | |||
if parentDir == "" { | |||
req = "baseDir=" + modelActualPath | |||
} else { | |||
req = "baseDir=" + modelActualPath + "&parentDir=" + parentDir | |||
} | |||
return getDirs(req) | |||
} | |||
func CloudBrainDownloadModel(ctx *context.Context) { | |||
parentDir := ctx.Query("parentDir") | |||
fileName := ctx.Query("fileName") | |||
jobName := ctx.Query("jobName") | |||
filePath := "jobs/" +jobName + "/model/" + parentDir | |||
url, err := storage.Attachments.PresignedGetURL(filePath, fileName) | |||
if err != nil { | |||
log.Error("PresignedGetURL failed: %v", err.Error(), ctx.Data["msgID"]) | |||
ctx.ServerError("PresignedGetURL", err) | |||
return | |||
} | |||
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently) | |||
} | |||
func GetRate(ctx *context.Context) { | |||
var jobID = ctx.Params(":jobid") | |||
job, err := models.GetCloudbrainByJobID(jobID) | |||
@@ -341,11 +420,11 @@ func GetRate(ctx *context.Context) { | |||
} | |||
if job.JobType == string(models.JobTypeBenchmark) { | |||
ctx.Redirect(setting.BenchmarkServerHost) | |||
ctx.Redirect(setting.BenchmarkServerHost + "?username=" + ctx.User.Name) | |||
} else if job.JobType == string(models.JobTypeSnn4imagenet) { | |||
ctx.Redirect(setting.Snn4imagenetServerHost) | |||
} else { | |||
log.Error("JobType error:", job.JobType) | |||
log.Error("JobType error:%s", job.JobType, ctx.Data["msgID"]) | |||
} | |||
} | |||
@@ -58,10 +58,10 @@ func DirIndex(ctx *context.Context) { | |||
dirArray = []string{attachment.Name} | |||
} | |||
dirs, err := getDirs(uuid, parentDir) | |||
dirs, err := getDatasetDirs(uuid, parentDir) | |||
if err != nil { | |||
log.Error("getDirs failed:", err.Error()) | |||
ctx.ServerError("getDirs failed:", err) | |||
log.Error("getDatasetDirs failed:", err.Error()) | |||
ctx.ServerError("getDatasetDirs failed:", err) | |||
return | |||
} | |||
@@ -75,20 +75,31 @@ func DirIndex(ctx *context.Context) { | |||
ctx.Data["Path"] = dirArray | |||
ctx.Data["Dirs"] = fileInfos | |||
ctx.Data["Uuid"] = uuid | |||
ctx.Data["PageIsDataset"] = true | |||
ctx.HTML(200, tplDirIndex) | |||
} | |||
func getDirs(uuid string, parentDir string) (string, error) { | |||
var dirs string | |||
func getDatasetDirs(uuid string, parentDir string) (string, error) { | |||
var req string | |||
dataActualPath := setting.Attachment.Minio.RealPath + | |||
setting.Attachment.Minio.Bucket + "/" + | |||
setting.Attachment.Minio.BasePath + | |||
models.AttachmentRelativePath(uuid) + | |||
uuid + "/" | |||
if parentDir == "" { | |||
req = "uuid=" + uuid | |||
req = "baseDir=" + dataActualPath | |||
} else { | |||
req = "uuid=" + uuid + "&parentDir=" + parentDir | |||
req = "baseDir=" + dataActualPath + "&parentDir=" + parentDir | |||
} | |||
return getDirs(req) | |||
} | |||
func getDirs(req string) (string, error) { | |||
var dirs string | |||
url := setting.DecompressAddress + "/dirs?" + req | |||
reqHttp, err := http.NewRequest(http.MethodGet, url, nil) | |||
if err != nil { | |||
@@ -127,6 +138,5 @@ func getDirs(uuid string, parentDir string) (string, error) { | |||
} | |||
dirs = resp.FileInfos | |||
return dirs, nil | |||
} |
@@ -8,6 +8,7 @@ package repo | |||
import ( | |||
"fmt" | |||
"io" | |||
"net/url" | |||
"path" | |||
"strings" | |||
@@ -32,6 +33,7 @@ func ServeData(ctx *context.Context, name string, reader io.Reader) error { | |||
// Google Chrome dislike commas in filenames, so let's change it to a space | |||
name = strings.Replace(name, ",", " ", -1) | |||
name = url.QueryEscape(name) | |||
if base.IsTextFile(buf) || ctx.QueryBool("render") { | |||
cs, err := charset.DetectEncoding(buf) | |||
@@ -49,6 +49,7 @@ import ( | |||
"gitea.com/macaron/session" | |||
"gitea.com/macaron/toolbox" | |||
"github.com/prometheus/client_golang/prometheus" | |||
gouuid "github.com/satori/go.uuid" | |||
"github.com/tstranex/u2f" | |||
) | |||
@@ -85,7 +86,7 @@ func setupAccessLogger(m *macaron.Macaron) { | |||
log.Error("Could not set up macaron access logger: %v", err.Error()) | |||
} | |||
err = logger.SendLog(log.INFO, "", "", 0, buf.String(), "") | |||
err = logger.SendLog(log.INFO, "", "", 0, buf.String(), ctx.Data["msgID"].(string), "") | |||
if err != nil { | |||
log.Error("Could not set up macaron access logger: %v", err.Error()) | |||
} | |||
@@ -107,6 +108,24 @@ func RouterHandler(level log.Level) func(ctx *macaron.Context) { | |||
} | |||
} | |||
// SetLogMsgID set msgID in Context | |||
func SetLogMsgID() func(ctx *macaron.Context) { | |||
return func(ctx *macaron.Context) { | |||
start := time.Now() | |||
uuid := gouuid.NewV4().String() | |||
ctx.Data["MsgID"] = uuid | |||
log.Info("Started %s %s for %s", log.ColoredMethod(ctx.Req.Method), ctx.Req.URL.RequestURI(), ctx.RemoteAddr(), ctx.Data["MsgID"]) | |||
rw := ctx.Resp.(macaron.ResponseWriter) | |||
ctx.Next() | |||
status := rw.Status() | |||
log.Info("Completed %s %s %v %s in %v", log.ColoredMethod(ctx.Req.Method), ctx.Req.URL.RequestURI(), log.ColoredStatus(status), log.ColoredStatus(status, http.StatusText(rw.Status())), log.ColoredTime(time.Since(start)), ctx.Data["MsgID"]) | |||
} | |||
} | |||
// NewMacaron initializes Macaron instance. | |||
func NewMacaron() *macaron.Macaron { | |||
gob.Register(&u2f.Challenge{}) | |||
@@ -125,6 +144,7 @@ func NewMacaron() *macaron.Macaron { | |||
m.Use(macaron.Logger()) | |||
} | |||
} | |||
m.Use(SetLogMsgID()) | |||
// Access Logger is similar to Router Log but more configurable and by default is more like the NCSA Common Log format | |||
if setting.EnableAccessLog { | |||
setupAccessLogger(m) | |||
@@ -910,9 +930,11 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
m.Post("/commit_image", reqRepoCloudBrainWriter, bindIgnErr(auth.CommitImageCloudBrainForm{}), repo.CloudBrainCommitImage) | |||
m.Post("/stop", reqRepoCloudBrainWriter, repo.CloudBrainStop) | |||
m.Post("/del", reqRepoCloudBrainWriter, repo.CloudBrainDel) | |||
m.Get("/rate", reqRepoCloudBrainWriter, repo.GetRate) | |||
m.Get("/rate", reqRepoCloudBrainReader, repo.GetRate) | |||
m.Get("/models", reqRepoCloudBrainReader, repo.CloudBrainShowModels) | |||
m.Get("/download_model", reqRepoCloudBrainReader, repo.CloudBrainDownloadModel) | |||
}) | |||
m.Get("/create", reqRepoCloudBrainWriter, repo.CloudBrainNew) | |||
m.Get("/create", reqRepoCloudBrainReader, repo.CloudBrainNew) | |||
m.Post("/create", reqRepoCloudBrainWriter, bindIgnErr(auth.CreateCloudBrainForm{}), repo.CloudBrainCreate) | |||
}, context.RepoRef()) | |||
@@ -535,7 +535,10 @@ func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyR | |||
log.Error("Unable to store session: %v", err) | |||
} | |||
// Language setting of the user overwrites the one previously set | |||
// Language setting of the user use the one previously set | |||
if len(ctx.GetCookie("lang")) != 0 { | |||
u.Language = ctx.GetCookie("lang") | |||
} | |||
// If the user does not have a locale set, we save the current one. | |||
if len(u.Language) == 0 { | |||
u.Language = ctx.Locale.Language() | |||
@@ -25,7 +25,7 @@ | |||
{{range .Datasets}} | |||
<div class="item"> | |||
<div class="ui header"> | |||
<a class="name" href="{{.Repo.Link}}/datasets"> | |||
<a class="name" href="{{.Repo.Link}}/datasets?type=0"> | |||
{{.Repo.OwnerName}} / {{.Title}} | |||
</a> | |||
<div class="ui right metas"> | |||
@@ -1,14 +1,16 @@ | |||
<div class="tablet only mobile only sixteen wide mobile sixteen wide tablet column row"> | |||
<div class="ui secondary pointing tabular top attached borderless menu navbar"> | |||
<a class="{{if $.PageIsOrgHome}}active{{end}} item" href="{{.HomeLink}}"> | |||
{{svg "octicon-home" 16}} {{$.i18n.Tr "org.组织主页"}} | |||
</a> | |||
<a class="{{if $.PageIsOrgMembers}}active{{end}} item" href="{{$.OrgLink}}/members"> | |||
{{svg "octicon-organization" 16}} {{$.i18n.Tr "org.people"}} | |||
</a> | |||
<a class="{{if $.PageIsOrgTeams}}active{{end}} item" href="{{$.OrgLink}}/teams"> | |||
{{svg "octicon-jersey" 16}} {{$.i18n.Tr "org.teams"}} | |||
{{svg "octicon-home" 16}} {{$.i18n.Tr "org.home"}} | |||
</a> | |||
{{if or ($.IsOrganizationMember) ($.IsOrganizationOwner)}} | |||
<a class="{{if $.PageIsOrgMembers}}active{{end}} item" href="{{$.OrgLink}}/members"> | |||
{{svg "octicon-organization" 16}} {{$.i18n.Tr "org.people"}} | |||
</a> | |||
<a class="{{if $.PageIsOrgTeams}}active{{end}} item" href="{{$.OrgLink}}/teams"> | |||
{{svg "octicon-jersey" 16}} {{$.i18n.Tr "org.teams"}} | |||
</a> | |||
{{end}} | |||
</div> | |||
</div> | |||
<!--平板、移动端--> | |||
@@ -18,15 +20,17 @@ | |||
<div class="sixteen wide column ui secondary sticky pointing tabular vertical menu"> | |||
{{with .Org}} | |||
<a class="{{if $.PageIsOrgHome}}active{{end}} item" href="{{.HomeLink}}"> | |||
{{svg "octicon-home" 16}} {{$.i18n.Tr "org.主页"}} | |||
{{svg "octicon-home" 16}} {{$.i18n.Tr "org.home"}} | |||
</a> | |||
{{end}} | |||
<a class="{{if $.PageIsOrgMembers}}active{{end}} item" href="{{$.OrgLink}}/members"> | |||
{{svg "octicon-organization" 16}} {{$.i18n.Tr "org.people"}} | |||
</a> | |||
<a class="{{if $.PageIsOrgTeams}}active{{end}} item" href="{{$.OrgLink}}/teams"> | |||
{{svg "octicon-jersey" 16}} {{$.i18n.Tr "org.teams"}} | |||
</a> | |||
{{if or ($.IsOrganizationMember) ($.IsOrganizationOwner)}} | |||
<a class="{{if $.PageIsOrgMembers}}active{{end}} item" href="{{$.OrgLink}}/members"> | |||
{{svg "octicon-organization" 16}} {{$.i18n.Tr "org.people"}} | |||
</a> | |||
<a class="{{if $.PageIsOrgTeams}}active{{end}} item" href="{{$.OrgLink}}/teams"> | |||
{{svg "octicon-jersey" 16}} {{$.i18n.Tr "org.teams"}} | |||
</a> | |||
{{end}} | |||
</div> | |||
</div> | |||
</div> |
@@ -248,7 +248,7 @@ | |||
</div> | |||
<!--任务状态 --> | |||
<div class="three wide column job-status" id="{{.JobID}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}"> | |||
<div class="two wide column job-status" id="{{.JobID}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}"> | |||
{{.Status}} | |||
</div> | |||
@@ -257,15 +257,6 @@ | |||
<span class="ui text center">{{svg "octicon-flame" 16}} {{TimeSinceUnix .CreatedUnix $.Lang}}</span> | |||
</div> | |||
<!-- 查看 --> | |||
<div class="one wide column"> | |||
<span class="ui text clipboard"> | |||
<a class="title" href="{{$.Link}}/{{.JobID}}"> | |||
<span class="fitted">查看</span> | |||
</a> | |||
</span> | |||
</div> | |||
<!-- 评分 --> | |||
<div class="one wide column"> | |||
<div class="ui text center clipboard"> | |||
@@ -304,6 +295,15 @@ | |||
</div> | |||
</div> | |||
<!-- 模型下载 --> | |||
<div class="two wide column"> | |||
<span class="ui text clipboard"> | |||
<a class="title" href="{{$.Link}}/{{.JobID}}/models"> | |||
<span class="fitted">模型下载</span> | |||
</a> | |||
</span> | |||
</div> | |||
<!-- 接收结果 --> | |||
<iframe src="" frameborder="0" name="iframeContent" style="display: none;"></iframe> | |||
<a class="imageBtn" style="{{if not .CanDebug}}color:#CCCCCC;cursor:pointer;pointer-events:none;{{end}}; font-size:16px; font-weight:bold" value="{{.CanDebug}}">提交镜像</a> | |||
@@ -0,0 +1,27 @@ | |||
{{if .Dirs}} | |||
<table id="repo-files-table" class="ui single line table"> | |||
<tbody> | |||
{{range .Dirs}} | |||
<tr> | |||
<td class="name four wide"> | |||
<span class="truncate"> | |||
<span class="octicon octicon-file-directory"></span> | |||
<a class="title" href="{{if .IsDir}}{{$.RepoLink}}/cloudbrain/{{$.JobID}}/models?parentDir={{.ParenDir}}{{else}}{{$.RepoLink}}/cloudbrain/{{$.JobID}}/download_model?parentDir={{.ParenDir}}&fileName={{.FileName}}&jobName={{$.task.JobName}}{{end}}"> | |||
<span class="fitted">{{if .IsDir}} {{svg "octicon-file-directory" 16}}{{else}}{{svg "octicon-file" 16}}{{end}}</span> {{.FileName}} | |||
</a> | |||
</span> | |||
</td> | |||
<td class="message nine wide"> | |||
<span class="truncate has-emoji"> | |||
{{.Size | FileSize}} | |||
</span> | |||
</td> | |||
<td class="text right age three wide"> | |||
<span class="time-since poping up">{{.ModTime}}</span> | |||
</td> | |||
</tr> | |||
{{end}} | |||
</tbody> | |||
</table> | |||
{{end}} |
@@ -0,0 +1,29 @@ | |||
{{template "base/head" .}} | |||
<div class="repository dataset dir-list view"> | |||
{{template "repo/header" .}} | |||
<form class="ui container"> | |||
<div class="ui stackable grid {{if .Error}}hide{{end}}" id="dir-content"> | |||
<div class="row"> | |||
<div class="column sixteen wide"> | |||
<p> | |||
{{ range $index, $item := .Path }}<a href='{{$.Link}}/?parentDir={{if gt $index 0}}{{DatasetPathJoin $.Path $index "/"}}{{else}}{{end}}'>{{ $item }}</a><span class="directory-seperator">/</span>{{ end }} | |||
</p> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="ui grid"> | |||
<div class="row"> | |||
<div class="ui sixteen wide column"> | |||
<div class="dir list"> | |||
{{template "repo/cloudbrain/models/dir_list" .}} | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</form> | |||
</div> | |||
{{template "base/footer" .}} |
@@ -6,7 +6,7 @@ | |||
<td class="name four wide"> | |||
<span class="truncate"> | |||
<span class="octicon octicon-file-directory"></span> | |||
<a class="title" href="{{if .IsDir}}{{$.RepoLink}}/datasets/dirs/{{.UUID}}?parentDir={{.ParenDir}}{{end}}"> | |||
<a class="title" href="{{if .IsDir}}{{$.RepoLink}}/datasets/dirs/{{$.Uuid}}?parentDir={{.ParenDir}}{{end}}"> | |||
<span class="fitted">{{if .IsDir}} {{svg "octicon-file-directory" 16}}{{else}}{{svg "octicon-file" 16}}{{end}}</span> {{.FileName}} | |||
</a> | |||
</span> | |||
@@ -76,8 +76,8 @@ | |||
{{.i18n.Tr "repo.issues.filter_sort"}}<i class="dropdown icon"></i> | |||
</span> | |||
<div class="menu"> | |||
<a class="item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.latest"}}</a> | |||
<a class="item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.oldest"}}</a> | |||
<a class="item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}&tab={{$.TabName}}&type={{.Type}}">{{.i18n.Tr "repo.issues.filter_sort.latest"}}</a> | |||
<a class="item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}&tab={{$.TabName}}&type={{.Type}}">{{.i18n.Tr "repo.issues.filter_sort.oldest"}}</a> | |||
</div> | |||
</div> | |||
</div> | |||