diff --git a/crontask/monkey.go b/crontask/monkey.go index a250a22..4b3a4d5 100644 --- a/crontask/monkey.go +++ b/crontask/monkey.go @@ -3,8 +3,10 @@ package crontask import ( "autogo/common" "autogo/dbsql" + "autogo/device" "autogo/models" "autogo/monkey" + "fmt" "strings" "time" @@ -18,54 +20,84 @@ func CheckMonkeyTasks() { } defer dbsql.Close(db) + db_oms, err := dbsql.GetConn(dbsql.DSN_qaoms()) + if err != nil { + return + } + defer dbsql.Close(db_oms) + var list []models.MonkeyTask db.Model(models.MonkeyTask{}).Where("status = ? AND is_del = 0", "WAITTING").Find(&list) // 运行等待中的任务 for _, task := range list { + // 获取当前时间并-24h + oneDayBefore := time.Now().Add(-24 * time.Hour) + timestampTime := time.Unix(int64(task.CreateTime), 0) + // 如果任务超过24小时则取消 + if timestampTime.Before(oneDayBefore) { + db.Table(task.TableName()).Model(models.MonkeyTask{}).Where("id = ?", task.Id).Update("status", "CANCEL") + fmt.Println("Monkey任务", task.Id, "已超时取消") + continue + } + + // 按平台执行逻辑 if task.Platform == "adr" { product_name := task.Product if strings.Contains(task.Product, "-") { product_name = strings.Split(task.Product, "-")[0] } - var device models.Device - db.Table("device").Model(models.Device{}).Where("project = ? AND product_name = ? AND platform = ? AND status = ?", task.Project, product_name, task.Platform, "online").First(&device) - if device.ID < 1 { + var d models.Device + db.Table("device").Model(models.Device{}).Where("project = ? AND product_name = ? AND platform = ? AND status = ?", task.Project, product_name, task.Platform, "online").First(&d) + if d.ID < 1 { // 没有空闲设备 continue } - db.Table("device").Model(models.Device{}).Where("udid = ?", device.Udid).Update("status", "busy") - go monkey.RunAndroidMonkeyCmd(task, device.Udid) - common.PushCorntaskLog("执行Monkey任务:" + task.Project + "-" + device.Udid) + // 占用设备 + db.Table("device").Model(models.Device{}).Where("udid = ?", d.Udid).Update("status", "busy") + go monkey.RunAndroidMonkeyCmd(task, d.Udid) + db.Table(task.TableName()).Model(models.MonkeyTask{}).Where("id = ?", task.Id).Update("start_time", time.Now().Unix()) + common.PushCorntaskLog("执行Monkey任务:" + task.Project + "-" + d.Udid) } else if task.Platform == "ios" { product_name := task.Product if strings.Contains(task.Product, "-") { product_name = strings.Split(task.Product, "-")[0] } - var device models.Device - db.Table("device").Model(models.Device{}).Where("project = ? AND product_name = ? AND platform = ? AND status = ?", task.Project, product_name, task.Platform, "online").First(&device) - if device.ID < 1 { + // 获取product.id + var _p models.ProductV2 + db_oms.Table(_p.TableName()).Model(models.DeviceV2{}).Where("product_line = ? AND platform = ?", product_name, "ios").Last(&_p) + if _p.ID < 1 { + fmt.Println("找不到产品,", product_name) + // 找不到对应的产品 + continue + } + // 获取产品对应的空闲设备 + var _d models.DeviceV2 + db_oms.Table(_d.TableName()).Model(models.DeviceV2{}).Where("product_id = ? AND platform = ? AND status = ? AND is_enabled = 1", _p.ID, task.Platform, "online").First(&_d) + if _d.ID < 1 { // 没有空闲设备 continue } - db.Table("device").Model(models.Device{}).Where("udid = ?", device.Udid).Update("status", "busy") - // go monkey.RunAndroidMonkeyCmd(task, device.Udid) - go monkey.RuniOSMonkeyByDocker(task, device.Udid) - common.PushCorntaskLog("执行Monkey任务:" + task.Project + "-" + device.Udid) + // 占用设备V2 + device.UpdateStatus(_d.Udid, "ready", "设备占用-Monkey任务"+cast.ToString(task.Id)+"") + // db.Table("device").Model(models.Device{}).Where("udid = ?", d.Udid).Update("status", "busy") + go monkey.RuniOSMonkeyByDocker(task, _d.Udid) + db.Table(task.TableName()).Model(models.MonkeyTask{}).Where("id = ?", task.Id).Update("start_time", time.Now().Unix()) + common.PushCorntaskLog("执行Monkey任务:" + task.Project + "-" + _d.Udid) } } // 判断运行中的任务的实际状态 db.Model(models.MonkeyTask{}).Where("status = ? AND is_del = 0", "RUNNING").Find(&list) - for i, v := range list { + for _, v := range list { if v.Platform == "adr" { // 如果无对应正在运行的容器,判断为【结束】或【异常停止】 if len(monkey.GetTaskFromDocker(v.Id)) == 0 { // 如果预期结束时间(任务开始时间+运行时间) < 当前时间,判断任务为运行正常结束 - if v.UpdateTime+v.RunTime < int(time.Now().Unix()) { - list[i].Status = "FINISH" - db.Table(v.TableName()).Model(models.MonkeyTask{}).Where("id = ?", v.Id).Update("status", list[i].Status) - common.PushMonkeyResult(v) + if v.StartTime+v.RunTime < int(time.Now().Unix()) { + // list[i].Status = "FINISH" + // db.Table(v.TableName()).Model(models.MonkeyTask{}).Where("id = ?", v.Id).Update("status", list[i].Status) + // common.PushMonkeyResult(v) } else { common.PushCorntaskLog("任务状态似乎异常,task_id=" + cast.ToString(v.Id)) } diff --git a/device/device_v2.go b/device/device_v2.go index 049f69d..1291f20 100644 --- a/device/device_v2.go +++ b/device/device_v2.go @@ -4,6 +4,7 @@ import ( "autogo/controllers" "autogo/dbsql" "autogo/models" + "errors" "net/http" "github.com/gin-gonic/gin" @@ -83,27 +84,88 @@ func UpdateDeviceStatusV2(c *gin.Context) { return } - db, err := dbsql.GetConn(dbsql.DSN_qaoms()) + // db, err := dbsql.GetConn(dbsql.DSN_qaoms()) + // if err != nil { + // rsp.Error(err.Error()) + // c.JSON(http.StatusOK, rsp) + // return + // } + // defer dbsql.Close(db) + + // var dv models.DeviceV2 + // db.Model(models.DeviceV2{}).Where("udid = ?", udid).Last(&dv) + // if dv.ID < 1 { + // c.JSON(http.StatusOK, rsp.Error("设备不存在: "+udid)) + // return + // } + // dv.Status = status + // dv.StatusDetails = status_details + + // db.Save(&dv) + + dv, err := UpdateStatus(udid, status, status_details) if err != nil { - rsp.Error(err.Error()) - c.JSON(http.StatusOK, rsp) + c.JSON(http.StatusOK, rsp.Error(err.Error())) return } - defer dbsql.Close(db) + rsp.Success() + rsp.Data = dv + c.JSON(http.StatusOK, rsp) +} + +func UpdateStatus(udid, status string, status_details ...string) (models.DeviceV2, error) { var dv models.DeviceV2 + db, err := dbsql.GetConn(dbsql.DSN_qaoms()) + if err != nil { + return dv, err + } + defer dbsql.Close(db) + db.Model(models.DeviceV2{}).Where("udid = ?", udid).Last(&dv) if dv.ID < 1 { - c.JSON(http.StatusOK, rsp.Error("设备不存在: "+udid)) - return + return dv, errors.New("设备不存在-" + udid) } dv.Status = status - dv.StatusDetails = status_details + if len(status_details) == 1 { + dv.StatusDetails = status_details[0] + } db.Save(&dv) + return dv, nil +} + +// @Tags 设备相关 /api/device/v2/ +// @Summary 更新设备IP +// @Description 更新设备IP +// @accept x-www-form-urlencoded +// @Param udid formData string true "设备udid" +// @Param ip formData string true "设备ip" +// @Success 200 {object} models.Response "返回更新的状态" +// @Router /api/device/v2/update_ip [post] +func UpdateDeviceIpV2(c *gin.Context) { + rsp := controllers.NewResponse() + + udid := c.PostForm("udid") + ip := c.PostForm("ip") + + if udid == "" { + c.JSON(http.StatusOK, rsp.Error("参数udid错误:"+udid)) + return + } + + db, err := dbsql.GetConn(dbsql.DSN_qaoms()) + if err != nil { + rsp.Error(err.Error()) + c.JSON(http.StatusOK, rsp) + return + } + defer dbsql.Close(db) + + db.Model(models.DeviceV2{}).Where("udid = ?", udid).Update("lan_ip", ip) rsp.Success() - rsp.Data = dv + rsp.Data = ip c.JSON(http.StatusOK, rsp) } diff --git a/docs/docs.go b/docs/docs.go index 0c9266b..8c35967 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -375,6 +375,42 @@ const docTemplate = `{ } } }, + "/api/device/v2/update_ip": { + "post": { + "description": "更新设备IP", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "设备相关 /api/device/v2/" + ], + "summary": "更新设备IP", + "parameters": [ + { + "type": "string", + "description": "设备udid", + "name": "udid", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "设备ip", + "name": "ip", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "返回更新的状态", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } + }, "/api/device/v2/update_status": { "post": { "description": "更新设备状态,错误的状态会被拒绝", diff --git a/docs/swagger.json b/docs/swagger.json index f15528c..f6ebd74 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -363,6 +363,42 @@ } } }, + "/api/device/v2/update_ip": { + "post": { + "description": "更新设备IP", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "设备相关 /api/device/v2/" + ], + "summary": "更新设备IP", + "parameters": [ + { + "type": "string", + "description": "设备udid", + "name": "udid", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "设备ip", + "name": "ip", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "返回更新的状态", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } + }, "/api/device/v2/update_status": { "post": { "description": "更新设备状态,错误的状态会被拒绝", diff --git a/docs/swagger.yaml b/docs/swagger.yaml index ed51dda..642cefd 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -282,6 +282,30 @@ paths: summary: 查询设备 tags: - 设备相关 /api/device/v2/ + /api/device/v2/update_ip: + post: + consumes: + - application/x-www-form-urlencoded + description: 更新设备IP + parameters: + - description: 设备udid + in: formData + name: udid + required: true + type: string + - description: 设备ip + in: formData + name: ip + required: true + type: string + responses: + "200": + description: 返回更新的状态 + schema: + $ref: '#/definitions/models.Response' + summary: 更新设备IP + tags: + - 设备相关 /api/device/v2/ /api/device/v2/update_status: post: consumes: diff --git a/models/monkey_task.go b/models/monkey_task.go index 1601fca..7dc14df 100644 --- a/models/monkey_task.go +++ b/models/monkey_task.go @@ -26,6 +26,8 @@ type MonkeyTask struct { Status string `json:"status" gorm:"column:status;type:varchar(255);not null;comment:运行状态"` HandleStatus string `json:"handle_status" gorm:"type:varchar(255);null"` Remark string `json:"remark" gorm:"column:remark;type:varchar(255);not null;comment:备注"` + StartTime int `json:"start_time" gorm:"column:start_time"` + EndTime int `json:"end_time" gorm:"column:end_time"` CreateTime int `json:"create_time" gorm:"column:create_time;type:int(11);not null;autoCreateTime;comment:创建时间"` UpdateTime int `json:"update_time" gorm:"column:update_time;type:int(11);not null;autoUpdateTime;comment:更新时间"` IsDel int `json:"is_del" gorm:"column:is_del;type:int(1);not null;comment:是否已删除"` diff --git a/models/oms_products.go b/models/oms_products.go new file mode 100644 index 0000000..a5c27bd --- /dev/null +++ b/models/oms_products.go @@ -0,0 +1,20 @@ +package models + +// Product 结构体 +type ProductV2 struct { + ID int `json:"id" gorm:"id"` + ProjectName string `json:"project_name" form:"project_name" gorm:"column:project_name;comment:项目名称;size:64;"` + ProjectLabel string `json:"project_label" form:"project_label" gorm:"column:project_label;comment:唯一且仅英文;size:32;"` + ExtId string `json:"project_ext_id" form:"project_ext_id" gorm:"column:project_ext_id;comment:例如teambition项目Id;"` + ProductLine string `json:"product_line" form:"product_line" gorm:"column:product_line;comment:不同环境的产品需要放在同一个产品线中;"` + ProductName string `json:"product_name" form:"product_name" gorm:"column:product_name;comment:;size:32;"` + ProductLabel string `json:"product_label" form:"product_label" gorm:"column:product_label;comment:唯一,用英文小写定义;"` + PackageName string `json:"package_name" form:"package_name" gorm:"column:package_name;comment:;"` + Platform string `json:"platform" form:"platform" gorm:"column:platform;comment:adr/ios/web等等;size:32;"` + Status int `json:"status" form:"status" gorm:"column:status;comment:预留状态字段;"` +} + +// TableName Product 表名 +func (ProductV2) TableName() string { + return "product" +} diff --git a/monkey/task.go b/monkey/task.go index c5b8af8..fd40f2f 100644 --- a/monkey/task.go +++ b/monkey/task.go @@ -9,6 +9,7 @@ import ( "net/http" "strconv" "strings" + "time" "github.com/gin-gonic/gin" "github.com/spf13/cast" @@ -131,6 +132,7 @@ func UpdateTaskStatus(c *gin.Context) { fmt.Println("更新设备状态为", status) if status == "FINISH" { + db.Table(task.TableName()).Model(models.MonkeyTask{}).Where("id = ?", task.Id).Update("end_time", time.Now().Unix()) common.PushMonkeyResult(task) } @@ -467,10 +469,25 @@ func StopMonkeyTask(c *gin.Context) { } } else if len(task.Devices) > 1 { // 有一台设备 - db.Table("device").Model(models.Device{}).Where("udid = ?", task.Devices).Update("status", "online") + if task.Platform == "adr" { + db.Table("device").Model(models.Device{}).Where("udid = ?", task.Devices).Update("status", "online") + } else if task.Platform == "ios" { + db_oms, err := dbsql.GetConn(dbsql.DSN_qaoms()) + if err != nil { + c.JSON(http.StatusOK, rsp.Error(err.Error())) + return + } + defer dbsql.Close(db_oms) + var dv models.DeviceV2 + db_oms.Table("qa_devices").Model(models.DeviceV2{}).Where("udid = ?", task.Devices).Last(&dv) + dv.Status = "online" + dv.StatusDetails = "Monkey-任务停止,释放设备" + db_oms.Save(&dv) + } } db.Table("monkey_task").Model(models.MonkeyTask{}).Where("id = ?", task_id).Update("status", "CANCEL") + db.Table("monkey_task").Model(models.MonkeyTask{}).Where("id = ?", task_id).Update("end_time", time.Now().Unix()) rsp.Data = "done" c.JSON(http.StatusOK, rsp.Success()) diff --git a/router/v2.go b/router/v2.go index c29c7e0..a919500 100644 --- a/router/v2.go +++ b/router/v2.go @@ -20,5 +20,6 @@ func setRouteV2(r *gin.Engine) { r.POST("/api/device/v2/create", device.CreateDeviceV2) r.POST("/api/device/v2/update_status", device.UpdateDeviceStatusV2) + r.POST("/api/device/v2/update_ip", device.UpdateDeviceIpV2) r.GET("/api/device/v2/get_device", device.GetDeviceByUdidV2) }