go-common/app/admin/ep/merlin/service/devicefarm.go
2019-04-22 18:49:16 +08:00

718 lines
19 KiB
Go

package service
import (
"context"
"fmt"
"time"
"go-common/app/admin/ep/merlin/model"
"go-common/library/ecode"
"go-common/library/log"
"github.com/satori/go.uuid"
)
//SyncMobileDeviceList Sync Device Farm List .
func (s *Service) SyncMobileDeviceList(c context.Context) (uid string, err error) {
uid = uuid.NewV4().String()
s.deviceChan.Do(c, func(c context.Context) {
var (
startCnt int
status int
totalCnt int
addCnt int
updateCnt int
delCnt int
err error
)
if startCnt, err = s.dao.FindMobileSyncLogStartStatus(); err != nil {
return
}
if startCnt > 0 {
return
}
mobileSyncLog := &model.MobileSyncLog{
UUID: uid,
}
s.dao.InsertMobileSyncLog(mobileSyncLog)
if totalCnt, addCnt, updateCnt, delCnt, err = s.SyncMobileDeviceListInChan(uid); err != nil {
status = -1
} else {
status = 1
}
mobileSyncLog = &model.MobileSyncLog{
UUID: uid,
TotalCnt: totalCnt,
AddCnt: addCnt,
UpdateCnt: updateCnt,
DeleteCnt: delCnt,
Status: status,
}
s.dao.UpdateMobileSyncLog(mobileSyncLog)
})
return
}
// SyncMobileDeviceListInChan Sync Mobile Device List In Chan.
func (s *Service) SyncMobileDeviceListInChan(uuid string) (totalCnt, addCnt, updateCnt, delCnt int, err error) {
var (
resTotal map[string][]*model.Device
)
if resTotal, err = s.dao.MobileDeviceList(context.Background()); err != nil {
log.Error("SyncMobileDeviceListInChan httpClient err(%+v)", err)
err = nil
}
if len(resTotal) == 0 {
return
}
for host, devices := range resTotal {
totalCnt = totalCnt + len(devices)
for _, device := range devices {
var deviceType int
var tmpMobileMachine *model.MobileMachine
if device.IsSimulator {
deviceType = model.MBSimulator
}
if tmpMobileMachine, err = s.dao.FindMobileMachineBySerial(device.Serial); err != nil {
log.Error("d.SyncMobileDeviceList FindMobileMachineBySerial err(%+v)", err)
continue
}
mobileMachine := &model.MobileMachine{
Serial: device.Serial,
Name: device.Name,
CPU: device.CPU,
Version: device.Version,
Mode: device.Mode,
State: device.State,
Host: host,
Type: deviceType,
Action: model.MBOnline,
UUID: uuid,
}
if tmpMobileMachine.ID == 0 {
if err = s.dao.InsertMobileMachine(mobileMachine); err != nil {
log.Error("d.SyncMobileDeviceList InsertMobileMachine err(%+v)", err)
} else {
addCnt = addCnt + 1
}
} else {
if err = s.dao.UpdateMobileMachine(mobileMachine); err != nil {
log.Error("d.SyncMobileDeviceList UpdateMobileMachine err(%+v)", err)
} else {
updateCnt = updateCnt + 1
}
}
}
}
s.dao.DeleteMobileMachineNotInHost(s.c.DeviceFarm.HostList)
delCnt, err = s.dao.DeleteMobileMachineByUUID(uuid)
return
}
// QueryMobileDeviceList Query Mobile Device List.
func (s *Service) QueryMobileDeviceList(c context.Context, queryRequest *model.QueryMobileDeviceRequest) (p *model.PaginateMobileMachines, err error) {
var (
total int64
mobileMachines []*model.MobileMachine
mobileMachinesResponse []*model.MobileMachineResponse
)
if total, mobileMachines, err = s.dao.FindMobileMachines(queryRequest); err != nil {
return
}
for _, mobileMachine := range mobileMachines {
var mobileMachineResponse model.MobileMachineResponse
mobileMachineResponse.MobileMachine = mobileMachine
mobileMachinesResponse = append(mobileMachinesResponse, &mobileMachineResponse)
}
if err = s.getMobileImages(mobileMachinesResponse); err != nil {
return
}
p = &model.PaginateMobileMachines{
PageNum: queryRequest.PageNum,
PageSize: queryRequest.PageSize,
Total: total,
MobileMachines: mobileMachinesResponse,
}
return
}
// RefreshMobileDeviceDetail Refresh Mobile Device Detail.
func (s *Service) RefreshMobileDeviceDetail(c context.Context, deviceID int64) (mobileMachineResponse *model.MobileMachineResponse, err error) {
var (
device *model.Device
mobileMachine *model.MobileMachine
)
if mobileMachine, err = s.dao.FindMobileMachineByID(deviceID); err != nil {
return
}
if device, err = s.dao.MobileDeviceDetail(c, mobileMachine.Host, mobileMachine.Serial); err != nil {
return
}
//update db
mobileMachine.State = device.State
mobileMachine.Action = 1
if err = s.dao.UpdateMobileMachine(mobileMachine); err != nil {
log.Error("d.RefreshMobileDeviceDetail err(%+v)", err)
return
}
mobileMachineResponse = &model.MobileMachineResponse{}
mobileMachineResponse.MobileMachine = mobileMachine
if err = s.getMobileImage(mobileMachineResponse); err != nil {
return
}
return
}
// MobileMachineCategory Mobile Machine Category.
func (s *Service) MobileMachineCategory(c context.Context, isShowOffline bool) (categoryList []*model.MobileDeviceCategoryResponse, err error) {
var mobileCategory *model.MobileCategory
if mobileCategory, err = s.dao.FindMobileMachineCategory(isShowOffline); err != nil {
return
}
interfaceCPU := make([]interface{}, len(mobileCategory.CPUs))
for i, v := range mobileCategory.CPUs {
interfaceCPU[i] = v
}
categoryCPU := &model.MobileDeviceCategoryResponse{
Name: "cpu",
Label: "CPU",
Values: interfaceCPU,
}
interfaceVersion := make([]interface{}, len(mobileCategory.Versions))
for i, v := range mobileCategory.Versions {
interfaceVersion[i] = v
}
categoryVersion := &model.MobileDeviceCategoryResponse{
Name: "version",
Label: "版本",
Values: interfaceVersion,
}
interfaceMode := make([]interface{}, len(mobileCategory.Modes))
for i, v := range mobileCategory.Modes {
interfaceMode[i] = v
}
categoryMode := &model.MobileDeviceCategoryResponse{
Name: "mode",
Label: "型号",
Values: interfaceMode,
}
interfaceType := make([]interface{}, len(mobileCategory.Types))
for i, v := range mobileCategory.Types {
interfaceType[i] = v
}
categoryType := &model.MobileDeviceCategoryResponse{
Name: "type",
Label: "是否真机",
Values: interfaceType,
}
interfaceState := make([]interface{}, len(mobileCategory.States))
for i, v := range mobileCategory.States {
interfaceState[i] = v
}
categoryState := &model.MobileDeviceCategoryResponse{
Name: "state",
Label: "状态",
Values: interfaceState,
}
interfaceUsage := make([]interface{}, len(mobileCategory.Usages))
for i, v := range mobileCategory.Usages {
interfaceUsage[i] = v
}
categoryUsage := &model.MobileDeviceCategoryResponse{
Name: "usage",
Label: "使用情况",
Values: interfaceUsage,
}
categoryList = append(categoryList, categoryCPU)
categoryList = append(categoryList, categoryVersion)
categoryList = append(categoryList, categoryMode)
categoryList = append(categoryList, categoryType)
categoryList = append(categoryList, categoryState)
categoryList = append(categoryList, categoryUsage)
return
}
// BindMobileDevice Bind Mobile Device.
func (s *Service) BindMobileDevice(c context.Context, deviceID int64, username string) (status int, err error) {
var mobileMachine *model.MobileMachine
status = -1
if mobileMachine, err = s.dao.FindMobileMachineByID(deviceID); err != nil {
return
}
if mobileMachine.Action < model.MBOnline {
err = ecode.MerlinDeviceFarmMachineStatusErr
return
}
//真机借出状态, 无法操作
if mobileMachine.Type == model.MBReal && mobileMachine.IsLendOut == model.MBLendOut {
err = ecode.MerlinDeviceIsLendOut
return
}
if mobileMachine.Username != "" {
return
}
mobileMachine.Username = username
mobileMachine.EndTime = time.Now().AddDate(0, s.c.DeviceFarm.ApplyMonthTime, 0)
mobileMachine.LastBindTime = time.Now()
if err = s.dao.UpdateMobileMachine(mobileMachine); err != nil {
return
}
if err = s.addMobileDeviceLog(deviceID, username, model.MBBindLog); err != nil {
return
}
status = 0
return
}
// ReleaseMobileDevice Release Mobile Device.
func (s *Service) ReleaseMobileDevice(c context.Context, deviceID int64, username string) (status int, err error) {
var mobileMachine *model.MobileMachine
status = -1
if mobileMachine, err = s.isAccessToMobileDevice(deviceID, username); err != nil {
return
}
mobileMachine.Username = ""
if mobileMachine.EndTime, err = time.ParseInLocation(model.TimeFormat, "1990-01-01 01:01:01", time.Local); err != nil {
return
}
if err = s.dao.UpdateMobileMachineByRelease(mobileMachine); err != nil {
return
}
if err = s.addMobileDeviceLog(deviceID, username, model.MBReleaseLog); err != nil {
return
}
status = 0
return
}
// LendOutMobileDevice Pull Out Mobile Device.
func (s *Service) LendOutMobileDevice(c context.Context, deviceID int64, username string) (status int, err error) {
var (
mobileMachine *model.MobileMachine
)
status = -1
if mobileMachine, err = s.isAccessToMobileDevice(deviceID, username); err != nil {
return
}
//只有真机支持借出 真机type=0
if mobileMachine.Type != model.MBReal {
err = ecode.MerlinDeviceIsNotRealMachineErr
return
}
if err = s.dao.LendOutMobileMachine(deviceID, mobileMachine.Serial, username); err != nil {
return
}
status = 0
return
}
// ReturnMobileDevice Return Mobile Device.
func (s *Service) ReturnMobileDevice(c context.Context, deviceID int64, username string) (status int, err error) {
var (
mobileMachine *model.MobileMachine
isSuperOwner = false
)
status = -1
for _, superOwner := range s.c.DeviceFarm.SuperOwner {
if username == superOwner {
isSuperOwner = true
break
}
}
if !isSuperOwner {
err = ecode.MerlinDeviceNoRight
return
}
if mobileMachine, err = s.dao.FindMobileMachineByID(deviceID); err != nil {
return
}
if mobileMachine.IsLendOut == model.MBOnSite {
err = ecode.MerlinDeviceFarmErr
return
}
if err = s.dao.ReturnMobileMachine(deviceID, mobileMachine.Serial, username); err != nil {
return
}
status = 0
return
}
// StartMobileDevice Start Mobile Device.
func (s *Service) StartMobileDevice(c context.Context, deviceID int64, username string) (deviceBootData *model.DeviceBootData, err error) {
var (
mobileMachine *model.MobileMachine
device *model.Device
)
if mobileMachine, err = s.isAccessToMobileDevice(deviceID, username); err != nil {
return
}
if deviceBootData, err = s.dao.BootMobileDevice(c, mobileMachine.Host, mobileMachine.Serial); err != nil {
return
}
if device, err = s.dao.MobileDeviceDetail(c, mobileMachine.Host, mobileMachine.Serial); err != nil {
return
}
mobileMachine.State = device.State
mobileMachine.WsURL = deviceBootData.WSRUL
mobileMachine.UploadURL = deviceBootData.UploadURL
if err = s.dao.UpdateMobileMachineWsurlAndState(mobileMachine); err != nil {
return
}
err = s.addMobileDeviceLog(deviceID, username, model.MBStartLog)
return
}
// ShutdownMobileDevice Shutdown Mobile Device.
func (s *Service) ShutdownMobileDevice(c context.Context, deviceID int64, username string) (status int, err error) {
var (
mobileMachine *model.MobileMachine
device *model.Device
)
status = -1
if mobileMachine, err = s.isAccessToMobileDevice(deviceID, username); err != nil {
return
}
if err = s.dao.ShutdownMobileDevice(c, mobileMachine.Host, mobileMachine.Serial); err != nil {
return
}
if device, err = s.dao.MobileDeviceDetail(c, mobileMachine.Host, mobileMachine.Serial); err != nil {
return
}
mobileMachine.State = device.State
mobileMachine.WsURL = ""
mobileMachine.UploadURL = ""
if err = s.dao.UpdateMobileMachineWsurlAndState(mobileMachine); err != nil {
return
}
if err = s.addMobileDeviceLog(deviceID, username, model.MBShutDownLog); err != nil {
return
}
status = 0
return
}
func (s *Service) isAccessToMobileDevice(deviceID int64, username string) (mobileMachine *model.MobileMachine, err error) {
if mobileMachine, err = s.dao.FindMobileMachineByID(deviceID); err != nil {
return
}
if mobileMachine.Action < model.MBOnline {
err = ecode.MerlinDeviceFarmMachineStatusErr
return
}
//真机借出状态, 无法操作
if mobileMachine.Type == model.MBReal && mobileMachine.IsLendOut == model.MBLendOut {
err = ecode.MerlinDeviceIsLendOut
return
}
for _, superOwner := range s.c.DeviceFarm.SuperOwner {
if username == superOwner {
return
}
}
if mobileMachine.Username != username {
err = ecode.MerlinDeviceNotBind
}
return
}
func (s *Service) addMobileDeviceLog(deviceID int64, username, operateType string) (err error) {
machineLog := &model.MobileMachineLog{
OperateType: operateType,
Username: username,
MachineID: deviceID,
OperateResult: model.OperationSuccessForMachineLog,
}
return s.dao.InsertMobileMachineLog(machineLog)
}
func (s *Service) getMobileImages(mobileMachinesResponse []*model.MobileMachineResponse) (err error) {
var mobileImages []*model.MobileImage
if mobileImages, err = s.dao.FindAllMobileImages(); err != nil {
return
}
for _, mobileMachineResponse := range mobileMachinesResponse {
for _, mobileImage := range mobileImages {
if mobileImage.Mode == mobileMachineResponse.Mode {
mobileMachineResponse.ImageSrc = mobileImage.ImageSrc
continue
}
}
}
return
}
func (s *Service) getMobileImage(mobileMachinesResponse *model.MobileMachineResponse) (err error) {
var mobileImage *model.MobileImage
if mobileImage, err = s.dao.FindMobileImageByMode(mobileMachinesResponse.Mode); err != nil {
return
}
mobileMachinesResponse.ImageSrc = mobileImage.ImageSrc
return
}
// QueryMobileMachineLogs Query Mobile Machine Logs.
func (s *Service) QueryMobileMachineLogs(c context.Context, queryRequest *model.QueryMobileMachineLogRequest) (p *model.PaginateMobileMachineLog, err error) {
var (
total int64
machineLogs []*model.AboundMobileMachineLog
)
if total, machineLogs, err = s.dao.FindMobileMachineLogs(queryRequest); err != nil {
return
}
p = &model.PaginateMobileMachineLog{
PageNum: queryRequest.PageNum,
PageSize: queryRequest.PageSize,
Total: total,
MachineLogs: machineLogs,
}
return
}
// QueryMobileMachineLendOutLogs Query Mobile Machine Lend Out Logs.
func (s *Service) QueryMobileMachineLendOutLogs(c context.Context, username string, queryRequest *model.QueryMobileMachineLogRequest) (p *model.PaginateMobileMachineLendOutLog, err error) {
var (
total int64
machineLogs []*model.AboundMobileMachineLog
machineLendOutRecords []*model.MachineLendOutRecord
mobileMachine *model.MobileMachine
existMachineIDs []int64
isSuperUser bool
)
isSuperUser = s.isSuperUser(username)
queryRequest.OperateType = model.MBLendOutLog
if total, machineLogs, err = s.dao.FindMobileMachineLogs(queryRequest); err != nil {
return
}
for _, machineLog := range machineLogs {
var (
enableReturn bool
isExistLendRecord bool
)
if mobileMachine, err = s.dao.FindMobileMachineByID(machineLog.MachineID); err != nil {
return
}
for _, existMachineID := range existMachineIDs {
if existMachineID == machineLog.MachineID {
isExistLendRecord = true
break
}
}
//移动设备借出状态 且 用户是超级用户 才有资格归还手机 只有最新一条记录 才能点击返还
if isExistLendRecord {
machineLendOutRecord := &model.MachineLendOutRecord{
MachineID: machineLog.MachineID,
Lender: machineLog.Username,
LendTime: machineLog.OperateTime,
EnableReturn: false,
Status: model.MBOnSite,
}
machineLendOutRecords = append(machineLendOutRecords, machineLendOutRecord)
} else {
if isSuperUser && (mobileMachine.IsLendOut == model.MBLendOut) {
enableReturn = true
}
machineLendOutRecord := &model.MachineLendOutRecord{
MachineID: machineLog.MachineID,
Lender: machineLog.Username,
LendTime: machineLog.OperateTime,
EnableReturn: enableReturn,
Status: mobileMachine.IsLendOut,
}
machineLendOutRecords = append(machineLendOutRecords, machineLendOutRecord)
existMachineIDs = append(existMachineIDs, machineLog.MachineID)
}
}
p = &model.PaginateMobileMachineLendOutLog{
PageNum: queryRequest.PageNum,
PageSize: queryRequest.PageSize,
Total: total,
MachineLendOutRecords: machineLendOutRecords,
}
return
}
// QueryMobileMachineErrorLogs Query Mobile Machine Error Logs.
func (s *Service) QueryMobileMachineErrorLogs(c context.Context, queryRequest *model.QueryMobileMachineErrorLogRequest) (p *model.PaginateMobileMachineErrorLog, err error) {
var (
total int64
machineLogs []*model.MobileMachineErrorLog
)
if total, machineLogs, err = s.dao.FindMobileMachineErrorLog(queryRequest); err != nil {
return
}
p = &model.PaginateMobileMachineErrorLog{
PageNum: queryRequest.PageNum,
PageSize: queryRequest.PageSize,
Total: total,
MachineLogs: machineLogs,
}
return
}
// CallBackMobileDeviceError Call Back Mobile Device Error.
func (s *Service) CallBackMobileDeviceError(c context.Context, serialName, errMsg string, errCode int) (err error) {
var mobileMachine *model.MobileMachine
if mobileMachine, err = s.dao.FindMobileMachineBySerial(serialName); err != nil {
return
}
mobileMachineErrorLog := &model.MobileMachineErrorLog{
MachineID: mobileMachine.ID,
SerialName: serialName,
ErrorMessage: errMsg,
ErrorCode: errCode,
}
err = s.dao.InsertMobileMachineErrorLog(mobileMachineErrorLog)
return
}
// ReportMobileDeviceError Report Mobile Device Error.
func (s *Service) ReportMobileDeviceError(c context.Context, serialName, errMsg string, errCode int) (err error) {
var mobileMachine *model.MobileMachine
if mobileMachine, err = s.dao.FindMobileMachineBySerial(serialName); err != nil {
return
}
if mobileMachine.ID == 0 {
err = ecode.NothingFound
return
}
content := fmt.Sprintf("通知\n设备ID: %d\n系列号: %s\n型号: %s\n系统版本: %s\n使用者: %s\n错误信息: %s\n错误码: %d", mobileMachine.ID, serialName, mobileMachine.Mode, mobileMachine.Version, mobileMachine.Username, errMsg, errCode)
msgSendReq := &model.MsgSendReq{
Chatid: s.c.WeChat.WeChatDeviceFarm.ChatID,
Msgtype: s.c.WeChat.WeChatDeviceFarm.MsgType,
Text: model.MsgSendReqText{Content: content},
Safe: s.c.WeChat.WeChatDeviceFarm.Safe,
}
if _, err = s.dao.WeChatSendMessage(c, msgSendReq); err != nil {
return
}
mobileMachineErrorLog := &model.MobileMachineErrorLog{
MachineID: mobileMachine.ID,
SerialName: serialName,
ErrorMessage: errMsg,
ErrorCode: errCode,
}
err = s.dao.InsertMobileMachineErrorLog(mobileMachineErrorLog)
return
}
// DeviceFarmSuperUser Device Farm Super User.
func (s *Service) DeviceFarmSuperUser() (responseMap map[string]interface{}) {
responseMap = make(map[string]interface{})
responseMap["superuser_list"] = s.c.DeviceFarm.SuperOwner
return
}
// IsBindMobileDeviceByTheUser Is Bind Mobile Device By The User.
func (s *Service) IsBindMobileDeviceByTheUser(c context.Context, deviceID int64, username string) (isBind bool, err error) {
var mobileMachine *model.MobileMachine
if mobileMachine, err = s.dao.FindMobileMachineByID(deviceID); err != nil {
return
}
if mobileMachine.Username == username {
isBind = true
}
return
}
func (s *Service) isSuperUser(username string) bool {
for _, superOwner := range s.c.DeviceFarm.SuperOwner {
if username == superOwner {
return true
}
}
return false
}