Browse Source

Merge pull request '解决pcm联调问题' (#30) from feature_gxh into master

pull/36/head
baohan 2 years ago
parent
commit
b319e27f6a
13 changed files with 457 additions and 193 deletions
  1. +0
    -3
      pkgs/distlock/internal/acquire_actor.go
  2. +15
    -17
      pkgs/logger/utils.go
  3. +36
    -0
      sdks/pcm/models.go
  4. +198
    -111
      sdks/pcm/pcm.go
  5. +58
    -0
      sdks/pcm/pcm_test.go
  6. +7
    -3
      sdks/scheduler/models.go
  7. +2
    -1
      sdks/storage/storage.go
  8. +31
    -34
      sdks/unifyops/models.go
  9. +6
    -14
      sdks/unifyops/unifyops.go
  10. +7
    -7
      sdks/unifyops/unifyops_test.go
  11. +19
    -3
      utils/http/http.go
  12. +43
    -0
      utils/serder/types.go
  13. +35
    -0
      utils/serder/types_test.go

+ 0
- 3
pkgs/distlock/internal/acquire_actor.go View File

@@ -173,8 +173,6 @@ func (a *AcquireActor) doAcquiring() error {
return err return err
} }


logger.Std.Infof("wait to: %d", index)

// 等待本地状态同步到最新 // 等待本地状态同步到最新
// TODO 配置等待时间 // TODO 配置等待时间
err = a.providersActor.WaitLocalIndexTo(ctx, index) err = a.providersActor.WaitLocalIndexTo(ctx, index)
@@ -190,7 +188,6 @@ func (a *AcquireActor) doAcquiring() error {


// 测试锁,并获得锁数据 // 测试锁,并获得锁数据
reqData, err := a.providersActor.TestLockRequestAndMakeData(req.Request) reqData, err := a.providersActor.TestLockRequestAndMakeData(req.Request)
logger.Std.Infof("6")
if err != nil { if err != nil {
req.LastErr = err req.LastErr = err
continue continue


+ 15
- 17
pkgs/logger/utils.go View File

@@ -11,24 +11,23 @@ type structFormatter struct {
} }


func (f *structFormatter) String() string { func (f *structFormatter) String() string {
typ := reflect.TypeOf(f.val)
val := reflect.ValueOf(f.val)

kind := typ.Kind()
realVal := reflect.ValueOf(f.val)
for {
kind := realVal.Type().Kind()

if kind == reflect.Struct {
sb := strings.Builder{}
f.structString(realVal, &sb)
return sb.String()
}


if kind == reflect.Struct {
sb := strings.Builder{}
f.structString(val, &sb)
return sb.String()
}
if kind == reflect.Pointer {
realVal = realVal.Elem()
continue
}


if kind == reflect.Pointer {
sb := strings.Builder{}
f.structString(val.Elem(), &sb)
return sb.String()
return fmt.Sprintf("%v", f.val)
} }

return fmt.Sprintf("%v", f.val)
} }


func (f *structFormatter) structString(val reflect.Value, strBuilder *strings.Builder) { func (f *structFormatter) structString(val reflect.Value, strBuilder *strings.Builder) {
@@ -94,8 +93,7 @@ func (f *structFormatter) structString(val reflect.Value, strBuilder *strings.Bu


// FormatStruct 输出结构体的内容。 // FormatStruct 输出结构体的内容。
// 1. 数组类型只会输出长度 // 1. 数组类型只会输出长度
// 2. 内部的结构体的内容不会再输出
// 3. 支持参数是一层的指针
// 2. 内部的结构体的内容不会再输出,包括embeded字段
func FormatStruct(val any) any { func FormatStruct(val any) any {
return &structFormatter{ return &structFormatter{
val: val, val: val,


+ 36
- 0
sdks/pcm/models.go View File

@@ -0,0 +1,36 @@
package pcmsdk

import schsdk "gitlink.org.cn/cloudream/common/sdks/scheduler"

type Participant struct {
ID schsdk.SlwNodeID `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
}

type Image struct {
ImageID schsdk.SlwNodeImageID `json:"imageID"`
ImageName string `json:"imageName"`
ImageStatus string `json:"imageStatus"`
}

type ResourceID string

type Resource struct {
ParticipantID schsdk.SlwNodeID `json:"participantID"`
ParticipantName string `json:"participantName"`
SpecName string `json:"specName"`
SpecID ResourceID `json:"specId"`
SpecPrice float64 `json:"specPrice"`
}

type TaskID string

type TaskStatus string

const (
TaskStatusPending TaskStatus = "Pending"
TaskStatusRunning TaskStatus = "Running"
TaskStatusSuccess TaskStatus = "Success"
TaskStatuFailed TaskStatus = "Failed"
)

+ 198
- 111
sdks/pcm/pcm.go View File

@@ -4,27 +4,29 @@ import (
"fmt" "fmt"
"net/url" "net/url"
"strings" "strings"
"time"


"gitlink.org.cn/cloudream/common/sdks"
schsdk "gitlink.org.cn/cloudream/common/sdks/scheduler" schsdk "gitlink.org.cn/cloudream/common/sdks/scheduler"
uopsdk "gitlink.org.cn/cloudream/common/sdks/unifyops"
myhttp "gitlink.org.cn/cloudream/common/utils/http" myhttp "gitlink.org.cn/cloudream/common/utils/http"
"gitlink.org.cn/cloudream/common/utils/serder" "gitlink.org.cn/cloudream/common/utils/serder"
) )


const CORRECT_CODE int = 200
const CodeOK int = 200


type UploadImageReq struct { type UploadImageReq struct {
SlwNodeID uopsdk.SlwNodeID `json:"slwNodeID"`
SlwNodeID schsdk.SlwNodeID `json:"slwNodeID"`
ImagePath string `json:"imagePath"` ImagePath string `json:"imagePath"`
} }


type UploadImageResp struct { type UploadImageResp struct {
Result string `json:"result"` Result string `json:"result"`
ImageID uopsdk.SlwNodeImageID `json:"imageID"`
ImageID schsdk.SlwNodeImageID `json:"imageID"`
} }


// TODO
func (c *Client) UploadImage(req UploadImageReq) (*UploadImageResp, error) { func (c *Client) UploadImage(req UploadImageReq) (*UploadImageResp, error) {
url, err := url.JoinPath(c.baseURL, "/pcm/v1/core/uploadImage")
url, err := url.JoinPath(c.baseURL, "/pcm/v1/storelink/uploadImage")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -43,7 +45,7 @@ func (c *Client) UploadImage(req UploadImageReq) (*UploadImageResp, error) {
return nil, fmt.Errorf("parsing response: %w", err) return nil, fmt.Errorf("parsing response: %w", err)
} }


if codeResp.Code == CORRECT_CODE {
if codeResp.Code == CodeOK {
return &codeResp.Data, nil return &codeResp.Data, nil
} }


@@ -53,200 +55,285 @@ func (c *Client) UploadImage(req UploadImageReq) (*UploadImageResp, error) {
return nil, fmt.Errorf("unknow response content type: %s", contType) return nil, fmt.Errorf("unknow response content type: %s", contType)
} }


type GetParticipantsResp struct {
Participants []Participant
}

func (c *Client) GetParticipants() (*GetParticipantsResp, error) {
type Resp struct {
Code int `json:"code"`
Message string `json:"message"`
Participants []Participant `json:"participants"`
}

url, err := url.JoinPath(c.baseURL, "/pcm/v1/storelink/uploadImage")
if err != nil {
return nil, err
}
rawResp, err := myhttp.GetJSON(url, myhttp.RequestParam{})
if err != nil {
return nil, err
}

resp, err := myhttp.ParseJSONResponse[Resp](rawResp)
if err != nil {
return nil, err
}

if resp.Code != CodeOK {
return nil, &sdks.CodeMessageError{
Code: fmt.Sprintf("%d", resp.Code),
Message: resp.Message,
}
}

return &GetParticipantsResp{
Participants: resp.Participants,
}, nil
}

type GetImageListReq struct { type GetImageListReq struct {
SlwNodeID int64 `json:"slwNodeID"`
PartID schsdk.SlwNodeID `json:"partId"`
} }


type GetImageListResp struct { type GetImageListResp struct {
ImageIDs []int64 `json:"imageIDs"`
Images []Image
} }


func (c *Client) GetImageList(req GetImageListReq) (*GetImageListResp, error) { func (c *Client) GetImageList(req GetImageListReq) (*GetImageListResp, error) {
url, err := url.JoinPath(c.baseURL, "/pcm/v1/core/getImageList")
type Resp struct {
Success bool `json:"success"`
Images []Image `json:"images"`
ErrorMsg string `json:"errorMsg"`
}

url, err := url.JoinPath(c.baseURL, "/pcm/v1/storelink/getImageList")
if err != nil { if err != nil {
return nil, err return nil, err
} }
resp, err := myhttp.PostJSON(url, myhttp.RequestParam{
rawResp, err := myhttp.GetJSON(url, myhttp.RequestParam{
Body: req, Body: req,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }


contType := resp.Header.Get("Content-Type")
if strings.Contains(contType, myhttp.ContentTypeJSON) {

var codeResp response[GetImageListResp]
if err := serder.JSONToObjectStream(resp.Body, &codeResp); err != nil {
return nil, fmt.Errorf("parsing response: %w", err)
}

if codeResp.Code == CORRECT_CODE {
return &codeResp.Data, nil
}
resp, err := myhttp.ParseJSONResponse[Resp](rawResp)
if err != nil {
return nil, err
}


return nil, codeResp.ToError()
if !resp.Success {
return nil, fmt.Errorf(resp.ErrorMsg)
} }


return nil, fmt.Errorf("unknow response content type: %s", contType)
return &GetImageListResp{
Images: resp.Images,
}, nil
} }


type DeleteImageReq struct { type DeleteImageReq struct {
SlwNodeID int64 `json:"slwNodeID"`
PCMJobID int64 `json:"pcmJobID"`
PartID schsdk.SlwNodeID `json:"partID"`
ImageID schsdk.SlwNodeImageID `json:"imageID"`
} }


type DeleteImageResp struct {
Result string `json:"result"`
}
func (c *Client) DeleteImage(req DeleteImageReq) error {
type Resp struct {
Success bool `json:"success"`
ErrorMsg string `json:"errorMsg"`
}


func (c *Client) DeleteImage(req DeleteImageReq) (*DeleteImageResp, error) {
url, err := url.JoinPath(c.baseURL, "/pcm/v1/core/deleteImage")
url, err := url.JoinPath(c.baseURL, "/pcm/v1/storelink/deleteImage")
if err != nil { if err != nil {
return nil, err
return err
} }
resp, err := myhttp.PostJSON(url, myhttp.RequestParam{
rawResp, err := myhttp.PostJSON(url, myhttp.RequestParam{
Body: req, Body: req,
}) })
if err != nil { if err != nil {
return nil, err
return err
} }


contType := resp.Header.Get("Content-Type")
if strings.Contains(contType, myhttp.ContentTypeJSON) {

var codeResp response[DeleteImageResp]
if err := serder.JSONToObjectStream(resp.Body, &codeResp); err != nil {
return nil, fmt.Errorf("parsing response: %w", err)
}

if codeResp.Code == CORRECT_CODE {
return &codeResp.Data, nil
}
resp, err := myhttp.ParseJSONResponse[Resp](rawResp)
if err != nil {
return err
}


return nil, codeResp.ToError()
if !resp.Success {
return fmt.Errorf(resp.ErrorMsg)
} }


return nil, fmt.Errorf("unknow response content type: %s", contType)
return nil
} }


type ScheduleTaskReq struct {
SlwNodeID uopsdk.SlwNodeID `json:"slwNodeID"`
Envs []schsdk.EnvVar `json:"envs"`
ImageID uopsdk.SlwNodeImageID `json:"imageID"`
CMDLine string `json:"cmdLine"`
type SubmitTaskReq struct {
PartID schsdk.SlwNodeID `json:"partId"`
ImageID schsdk.SlwNodeImageID `json:"imageId"`
ResourceID ResourceID `json:"resourceId"`
CMD string `json:"cmd"`
Params []schsdk.KVPair `json:"params"`
Envs []schsdk.KVPair `json:"envs"`
} }


type ScheduleTaskResp struct {
Result string `json:"result"`
PCMJobID int64 `json:"pcmJobID"`
type SubmitTaskResp struct {
TaskID TaskID
} }


func (c *Client) ScheduleTask(req ScheduleTaskReq) (*ScheduleTaskResp, error) {
url, err := url.JoinPath(c.baseURL, "/pcm/v1/core/scheduleTask")
func (c *Client) SubmitTask(req SubmitTaskReq) (*SubmitTaskResp, error) {
type Resp struct {
Success bool `json:"success"`
TaskID TaskID `json:"taskId"`
ErrorMsg string `json:"errorMsg"`
}

url, err := url.JoinPath(c.baseURL, "/pcm/v1/storelink/submitTask")
if err != nil { if err != nil {
return nil, err return nil, err
} }
resp, err := myhttp.PostJSON(url, myhttp.RequestParam{
rawResp, err := myhttp.PostJSON(url, myhttp.RequestParam{
Body: req, Body: req,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }


contType := resp.Header.Get("Content-Type")
if strings.Contains(contType, myhttp.ContentTypeJSON) {

var codeResp response[ScheduleTaskResp]
if err := serder.JSONToObjectStream(resp.Body, &codeResp); err != nil {
return nil, fmt.Errorf("parsing response: %w", err)
}

if codeResp.Code == CORRECT_CODE {
return &codeResp.Data, nil
}
resp, err := myhttp.ParseJSONResponse[Resp](rawResp)
if err != nil {
return nil, err
}


return nil, codeResp.ToError()
if !resp.Success {
return nil, fmt.Errorf(resp.ErrorMsg)
} }


return nil, fmt.Errorf("unknow response content type: %s", contType)
return &SubmitTaskResp{
TaskID: resp.TaskID,
}, nil
} }


type GetTaskStatusReq struct {
SlwNodeID uopsdk.SlwNodeID `json:"slwNodeID"`
PCMJobID int64 `json:"pcmJobID"`
type GetTaskReq struct {
PartID schsdk.SlwNodeID `json:"partId"`
TaskID TaskID `json:"taskId"`
} }


type GetTaskStatusResp struct {
Result string `json:"result"`
Status string `json:"status"`
type GetTaskResp struct {
TaskStatus TaskStatus
TaskName string
StartedAt time.Time
CompletedAt time.Time
} }


func (c *Client) GetTaskStatus(req GetTaskStatusReq) (*GetTaskStatusResp, error) {
url, err := url.JoinPath(c.baseURL, "/pcm/v1/core/getTaskStatus")
func (c *Client) GetTask(req GetTaskReq) (*GetTaskResp, error) {
type Resp struct {
Success bool `json:"success"`
Task struct {
TaskID TaskID `json:"taskId"`
TaskStatus TaskStatus `json:"taskStatus"`
TaskName string `json:"taskName"`
StartedAt serder.TimestampSecond `json:"startedAt"`
CompletedAt serder.TimestampSecond `json:"completedAt"`
} `json:"task"`
ErrorMsg string `json:"errorMsg"`
}

url, err := url.JoinPath(c.baseURL, "/pcm/v1/storelink/getTask")
if err != nil { if err != nil {
return nil, err return nil, err
} }
resp, err := myhttp.PostJSON(url, myhttp.RequestParam{
rawResp, err := myhttp.GetJSON(url, myhttp.RequestParam{
Body: req, Body: req,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }


contType := resp.Header.Get("Content-Type")
if strings.Contains(contType, myhttp.ContentTypeJSON) {
resp, err := myhttp.ParseJSONResponse[Resp](rawResp)
if err != nil {
return nil, err
}


var codeResp response[GetTaskStatusResp]
if err := serder.JSONToObjectStream(resp.Body, &codeResp); err != nil {
return nil, fmt.Errorf("parsing response: %w", err)
}
if !resp.Success {
return nil, fmt.Errorf(resp.ErrorMsg)
}


if codeResp.Code == CORRECT_CODE {
return &codeResp.Data, nil
}
return &GetTaskResp{
TaskStatus: resp.Task.TaskStatus,
TaskName: resp.Task.TaskName,
StartedAt: time.Time(resp.Task.StartedAt),
CompletedAt: time.Time(resp.Task.CompletedAt),
}, nil
}


return nil, codeResp.ToError()
type DeleteTaskReq struct {
PartID schsdk.SlwNodeID `json:"partId"`
TaskID TaskID `json:"taskId"`
}

func (c *Client) DeleteTask(req DeleteTaskReq) error {
type Resp struct {
Success bool `json:"success"`
ErrorMsg string `json:"errorMsg"`
} }


return nil, fmt.Errorf("unknow response content type: %s", contType)
url, err := url.JoinPath(c.baseURL, "/pcm/v1/storelink/deleteTask")
if err != nil {
return err
}
rawResp, err := myhttp.PostJSON(url, myhttp.RequestParam{
Body: req,
})
if err != nil {
return err
}

resp, err := myhttp.ParseJSONResponse[Resp](rawResp)
if err != nil {
return err
}

if !resp.Success {
return fmt.Errorf(resp.ErrorMsg)
}

return nil
} }


type DeleteTaskReq struct {
SlwNodeID int64 `json:"slwNodeID"`
PCMJobID int64 `json:"pcmJobID"`
type GetResourceSpecs struct {
PartID schsdk.SlwNodeID `json:"partId"`
} }


type DeleteTaskResp struct {
Result string `json:"result"`
type GetResourceSpecsResp struct {
Resources []Resource
} }


func (c *Client) DeleteTask(req DeleteTaskReq) (*DeleteTaskResp, error) {
url, err := url.JoinPath(c.baseURL, "/pcm/v1/core/deleteTask")
func (c *Client) GetResourceSpecs(req GetImageListReq) (*GetResourceSpecsResp, error) {
type Resp struct {
Success bool `json:"success"`
ResourceSpecs []Resource `json:"resourceSpecs"`
ErrorMsg string `json:"errorMsg"`
}

url, err := url.JoinPath(c.baseURL, "/pcm/v1/storelink/getResourceSpecs")
if err != nil { if err != nil {
return nil, err return nil, err
} }
resp, err := myhttp.PostJSON(url, myhttp.RequestParam{
rawResp, err := myhttp.GetJSON(url, myhttp.RequestParam{
Body: req, Body: req,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }


contType := resp.Header.Get("Content-Type")
if strings.Contains(contType, myhttp.ContentTypeJSON) {

var codeResp response[DeleteTaskResp]
if err := serder.JSONToObjectStream(resp.Body, &codeResp); err != nil {
return nil, fmt.Errorf("parsing response: %w", err)
}

if codeResp.Code == CORRECT_CODE {
return &codeResp.Data, nil
}
resp, err := myhttp.ParseJSONResponse[Resp](rawResp)
if err != nil {
return nil, err
}


return nil, codeResp.ToError()
if !resp.Success {
return nil, fmt.Errorf(resp.ErrorMsg)
} }


return nil, fmt.Errorf("unknow response content type: %s", contType)
return &GetResourceSpecsResp{
Resources: resp.ResourceSpecs,
}, nil
} }

+ 58
- 0
sdks/pcm/pcm_test.go View File

@@ -0,0 +1,58 @@
package pcmsdk

import (
"testing"
"time"

. "github.com/smartystreets/goconvey/convey"
schsdk "gitlink.org.cn/cloudream/common/sdks/scheduler"
)

func Test_SubmitTask(t *testing.T) {
Convey("提交任务,查询任务", t, func() {
cli := NewClient(&Config{
URL: "http://localhost:8889",
})

submitResp, err := cli.SubmitTask(SubmitTaskReq{
PartID: 1711652475901054976,
ImageID: "1d1769857cd64c03928c8a1a4ee4a23f",
ResourceID: "6388d3c27f654fa5b11439a3d6098dbc",
CMD: "echo $asd",
Envs: []schsdk.KVPair{{
Key: "asd",
Value: "hello",
}},
Params: []schsdk.KVPair{},
})
So(err, ShouldBeNil)

t.Logf("taskID: %s", submitResp.TaskID)

taskResp, err := cli.GetTask(GetTaskReq{
PartID: 1711652475901054976,
TaskID: submitResp.TaskID,
})
So(err, ShouldBeNil)

<-time.After(time.Second * 3)

t.Logf("taskName: %s, taskStatus: %s, startedAt: %v", taskResp.TaskName, taskResp.TaskStatus, taskResp.StartedAt)
})

}

func Test_GetImageList(t *testing.T) {
Convey("查询镜像列表", t, func() {
cli := NewClient(&Config{
URL: "http://localhost:8889",
})

getReps, err := cli.GetImageList(GetImageListReq{
PartID: 1711652475901054976,
})
So(err, ShouldBeNil)

t.Logf("imageList: %v", getReps.Images)
})
}

+ 7
- 3
sdks/scheduler/models.go View File

@@ -23,6 +23,10 @@ type JobSetID string


type ImageID string type ImageID string


type SlwNodeID int64

type SlwNodeImageID string

type JobSetInfo struct { type JobSetInfo struct {
Jobs []JobInfo `json:"jobs"` Jobs []JobInfo `json:"jobs"`
} }
@@ -111,11 +115,11 @@ type ImageJobFileInfo struct {


type JobRuntimeInfo struct { type JobRuntimeInfo struct {
Command string `json:"command"` Command string `json:"command"`
Envs []EnvVar `json:"envs"`
Envs []KVPair `json:"envs"`
} }


type EnvVar struct {
Var string `json:"var"`
type KVPair struct {
Key string `json:"key"`
Value string `json:"value"` Value string `json:"value"`
} }




+ 2
- 1
sdks/storage/storage.go View File

@@ -88,6 +88,7 @@ func (c *Client) StorageCreatePackage(req StorageCreatePackageReq) (*StorageCrea
} }


type StorageGetInfoReq struct { type StorageGetInfoReq struct {
UserID int64 `json:"userID"`
StorageID int64 `json:"storageID"` StorageID int64 `json:"storageID"`
} }
type StorageGetInfoResp struct { type StorageGetInfoResp struct {
@@ -103,7 +104,7 @@ func (c *Client) StorageGetInfo(req StorageGetInfoReq) (*StorageGetInfoResp, err
} }


resp, err := myhttp.GetForm(url, myhttp.RequestParam{ resp, err := myhttp.GetForm(url, myhttp.RequestParam{
Body: req,
Query: req,
}) })
if err != nil { if err != nil {
return nil, err return nil, err


+ 31
- 34
sdks/unifyops/models.go View File

@@ -3,6 +3,7 @@ package uopsdk
import ( import (
"gitlink.org.cn/cloudream/common/pkgs/mq" "gitlink.org.cn/cloudream/common/pkgs/mq"
"gitlink.org.cn/cloudream/common/pkgs/types" "gitlink.org.cn/cloudream/common/pkgs/types"
schsdk "gitlink.org.cn/cloudream/common/sdks/scheduler"
"gitlink.org.cn/cloudream/common/utils/serder" "gitlink.org.cn/cloudream/common/utils/serder"
) )


@@ -17,16 +18,12 @@ const (
ResourceTypeMemory ResourceType = "MEMORY" ResourceTypeMemory ResourceType = "MEMORY"
) )


type SlwNodeID int64

type SlwNodeImageID int64

type SlwNode struct { type SlwNode struct {
ID SlwNodeID `json:"ID"`
Name string `json:"name"`
SlwRegionID int64 `json:"slwRegionID"`
StgNodeID int64 `json:"stgNodeID"`
StorageID int64 `json:"StorageID"`
ID schsdk.SlwNodeID `json:"id"`
Name string `json:"name"`
SlwRegionID int64 `json:"slwRegionID"`
StgNodeID int64 `json:"stgNodeID"`
StorageID int64 `json:"StorageID"`
} }


type ResourceData interface { type ResourceData interface {
@@ -48,19 +45,19 @@ type ResourceDataBase struct{}


func (d *ResourceDataBase) Noop() {} func (d *ResourceDataBase) Noop() {}


type DetailType[T any] struct {
type UnitValue[T any] struct {
Unit string `json:"unit"` Unit string `json:"unit"`
Value T `json:"value"` Value T `json:"value"`
} }


type CPUResourceData struct { type CPUResourceData struct {
ResourceDataBase ResourceDataBase
Name ResourceType `json:"name" union:"CPU"`
Total DetailType[int64] `json:"total"`
Available DetailType[int64] `json:"available"`
Name ResourceType `json:"name" union:"CPU"`
Total UnitValue[int64] `json:"total"`
Available UnitValue[int64] `json:"available"`
} }


func NewCPUResourceData(total DetailType[int64], available DetailType[int64]) *CPUResourceData {
func NewCPUResourceData(total UnitValue[int64], available UnitValue[int64]) *CPUResourceData {
return &CPUResourceData{ return &CPUResourceData{
Name: ResourceTypeCPU, Name: ResourceTypeCPU,
Total: total, Total: total,
@@ -70,12 +67,12 @@ func NewCPUResourceData(total DetailType[int64], available DetailType[int64]) *C


type NPUResourceData struct { type NPUResourceData struct {
ResourceDataBase ResourceDataBase
Name ResourceType `json:"name" union:"NPU"`
Total DetailType[int64] `json:"total"`
Available DetailType[int64] `json:"available"`
Name ResourceType `json:"name" union:"NPU"`
Total UnitValue[int64] `json:"total"`
Available UnitValue[int64] `json:"available"`
} }


func NewNPUResourceData(total DetailType[int64], available DetailType[int64]) *NPUResourceData {
func NewNPUResourceData(total UnitValue[int64], available UnitValue[int64]) *NPUResourceData {
return &NPUResourceData{ return &NPUResourceData{
Name: ResourceTypeNPU, Name: ResourceTypeNPU,
Total: total, Total: total,
@@ -85,12 +82,12 @@ func NewNPUResourceData(total DetailType[int64], available DetailType[int64]) *N


type GPUResourceData struct { type GPUResourceData struct {
ResourceDataBase ResourceDataBase
Name ResourceType `json:"name" union:"GPU"`
Total DetailType[int64] `json:"total"`
Available DetailType[int64] `json:"available"`
Name ResourceType `json:"name" union:"GPU"`
Total UnitValue[int64] `json:"total"`
Available UnitValue[int64] `json:"available"`
} }


func NewGPUResourceData(total DetailType[int64], available DetailType[int64]) *GPUResourceData {
func NewGPUResourceData(total UnitValue[int64], available UnitValue[int64]) *GPUResourceData {
return &GPUResourceData{ return &GPUResourceData{
Name: ResourceTypeGPU, Name: ResourceTypeGPU,
Total: total, Total: total,
@@ -100,12 +97,12 @@ func NewGPUResourceData(total DetailType[int64], available DetailType[int64]) *G


type MLUResourceData struct { type MLUResourceData struct {
ResourceDataBase ResourceDataBase
Name ResourceType `json:"name" union:"MLU"`
Total DetailType[int64] `json:"total"`
Available DetailType[int64] `json:"available"`
Name ResourceType `json:"name" union:"MLU"`
Total UnitValue[int64] `json:"total"`
Available UnitValue[int64] `json:"available"`
} }


func NewMLUResourceData(total DetailType[int64], available DetailType[int64]) *MLUResourceData {
func NewMLUResourceData(total UnitValue[int64], available UnitValue[int64]) *MLUResourceData {
return &MLUResourceData{ return &MLUResourceData{
Name: ResourceTypeMLU, Name: ResourceTypeMLU,
Total: total, Total: total,
@@ -115,12 +112,12 @@ func NewMLUResourceData(total DetailType[int64], available DetailType[int64]) *M


type StorageResourceData struct { type StorageResourceData struct {
ResourceDataBase ResourceDataBase
Name ResourceType `json:"name" union:"STORAGE"`
Total DetailType[float64] `json:"total"`
Available DetailType[float64] `json:"available"`
Name ResourceType `json:"name" union:"STORAGE"`
Total UnitValue[float64] `json:"total"`
Available UnitValue[float64] `json:"available"`
} }


func NewStorageResourceData(total DetailType[float64], available DetailType[float64]) *StorageResourceData {
func NewStorageResourceData(total UnitValue[float64], available UnitValue[float64]) *StorageResourceData {
return &StorageResourceData{ return &StorageResourceData{
Name: ResourceTypeStorage, Name: ResourceTypeStorage,
Total: total, Total: total,
@@ -130,12 +127,12 @@ func NewStorageResourceData(total DetailType[float64], available DetailType[floa


type MemoryResourceData struct { type MemoryResourceData struct {
ResourceDataBase ResourceDataBase
Name ResourceType `json:"name" union:"MEMORY"`
Total DetailType[float64] `json:"total"`
Available DetailType[float64] `json:"available"`
Name ResourceType `json:"name" union:"MEMORY"`
Total UnitValue[float64] `json:"total"`
Available UnitValue[float64] `json:"available"`
} }


func NewMemoryResourceData(total DetailType[float64], available DetailType[float64]) *MemoryResourceData {
func NewMemoryResourceData(total UnitValue[float64], available UnitValue[float64]) *MemoryResourceData {
return &MemoryResourceData{ return &MemoryResourceData{
Name: ResourceTypeMemory, Name: ResourceTypeMemory,
Total: total, Total: total,


+ 6
- 14
sdks/unifyops/unifyops.go View File

@@ -5,17 +5,14 @@ import (
"net/url" "net/url"
"strings" "strings"


schsdk "gitlink.org.cn/cloudream/common/sdks/scheduler"
myhttp "gitlink.org.cn/cloudream/common/utils/http" myhttp "gitlink.org.cn/cloudream/common/utils/http"
"gitlink.org.cn/cloudream/common/utils/serder" "gitlink.org.cn/cloudream/common/utils/serder"
) )


const CORRECT_CODE int = 200 const CORRECT_CODE int = 200


type GetAllSlwNodeInfoResp struct {
Nodes []SlwNode `json:"nodes"`
}

func (c *Client) GetAllSlwNodeInfo() (*GetAllSlwNodeInfoResp, error) {
func (c *Client) GetAllSlwNodeInfo() ([]SlwNode, error) {
url, err := url.JoinPath(c.baseURL, "/cmdb/resApi/getSlwNodeInfo") url, err := url.JoinPath(c.baseURL, "/cmdb/resApi/getSlwNodeInfo")
if err != nil { if err != nil {
return nil, err return nil, err
@@ -27,13 +24,13 @@ func (c *Client) GetAllSlwNodeInfo() (*GetAllSlwNodeInfoResp, error) {
contType := resp.Header.Get("Content-Type") contType := resp.Header.Get("Content-Type")
if strings.Contains(contType, myhttp.ContentTypeJSON) { if strings.Contains(contType, myhttp.ContentTypeJSON) {


var codeResp response[GetAllSlwNodeInfoResp]
var codeResp response[[]SlwNode]
if err := serder.JSONToObjectStream(resp.Body, &codeResp); err != nil { if err := serder.JSONToObjectStream(resp.Body, &codeResp); err != nil {
return nil, fmt.Errorf("parsing response: %w", err) return nil, fmt.Errorf("parsing response: %w", err)
} }


if codeResp.Code == CORRECT_CODE { if codeResp.Code == CORRECT_CODE {
return &codeResp.Data, nil
return codeResp.Data, nil
} }


return nil, codeResp.ToError() return nil, codeResp.ToError()
@@ -43,7 +40,7 @@ func (c *Client) GetAllSlwNodeInfo() (*GetAllSlwNodeInfoResp, error) {
} }


type GetOneResourceDataReq struct { type GetOneResourceDataReq struct {
SlwNodeID SlwNodeID `json:"nodeId"`
SlwNodeID schsdk.SlwNodeID `json:"nodeId"`
} }


func (c *Client) GetCPUData(node GetOneResourceDataReq) (*CPUResourceData, error) { func (c *Client) GetCPUData(node GetOneResourceDataReq) (*CPUResourceData, error) {
@@ -250,15 +247,10 @@ func (c *Client) GetIndicatorData(node GetOneResourceDataReq) (*[]ResourceData,
return nil, codeResp.ToError() return nil, codeResp.ToError()
} }


mapToObjOpt := serder.MapToObjectOption{
UnionTypes: []serder.TaggedUnionType{
ResourceDataTaggedTypeUnion,
},
}
var ret []ResourceData var ret []ResourceData
for _, mp := range codeResp.Data { for _, mp := range codeResp.Data {
var data ResourceData var data ResourceData
err := serder.MapToObject(mp, &data, mapToObjOpt)
err := serder.MapToObject(mp, &data)
if err != nil { if err != nil {
return nil, err return nil, err
} }


+ 7
- 7
sdks/unifyops/unifyops_test.go View File

@@ -17,43 +17,43 @@ func Test_UnifyOps(t *testing.T) {
So(err, ShouldBeNil) So(err, ShouldBeNil)


cpuData, err := cli.GetCPUData(GetOneResourceDataReq{ cpuData, err := cli.GetCPUData(GetOneResourceDataReq{
SlwNodeID: slwNodeInfos.Nodes[0].ID,
SlwNodeID: slwNodeInfos[0].ID,
}) })
So(err, ShouldBeNil) So(err, ShouldBeNil)
fmt.Printf("cpuData: %v\n", cpuData) fmt.Printf("cpuData: %v\n", cpuData)


gpuData, err := cli.GetGPUData(GetOneResourceDataReq{ gpuData, err := cli.GetGPUData(GetOneResourceDataReq{
SlwNodeID: slwNodeInfos.Nodes[0].ID,
SlwNodeID: slwNodeInfos[0].ID,
}) })
So(err, ShouldBeNil) So(err, ShouldBeNil)
fmt.Printf("gpuData: %v\n", gpuData) fmt.Printf("gpuData: %v\n", gpuData)


npuData, err := cli.GetNPUData(GetOneResourceDataReq{ npuData, err := cli.GetNPUData(GetOneResourceDataReq{
SlwNodeID: slwNodeInfos.Nodes[0].ID,
SlwNodeID: slwNodeInfos[0].ID,
}) })
So(err, ShouldBeNil) So(err, ShouldBeNil)
fmt.Printf("npuData: %v\n", npuData) fmt.Printf("npuData: %v\n", npuData)


mluData, err := cli.GetMLUData(GetOneResourceDataReq{ mluData, err := cli.GetMLUData(GetOneResourceDataReq{
SlwNodeID: slwNodeInfos.Nodes[0].ID,
SlwNodeID: slwNodeInfos[0].ID,
}) })
So(err, ShouldBeNil) So(err, ShouldBeNil)
fmt.Printf("mluData: %v\n", mluData) fmt.Printf("mluData: %v\n", mluData)


storageData, err := cli.GetStorageData(GetOneResourceDataReq{ storageData, err := cli.GetStorageData(GetOneResourceDataReq{
SlwNodeID: slwNodeInfos.Nodes[0].ID,
SlwNodeID: slwNodeInfos[0].ID,
}) })
So(err, ShouldBeNil) So(err, ShouldBeNil)
fmt.Printf("storageData: %v\n", storageData) fmt.Printf("storageData: %v\n", storageData)


memoryData, err := cli.GetMemoryData(GetOneResourceDataReq{ memoryData, err := cli.GetMemoryData(GetOneResourceDataReq{
SlwNodeID: slwNodeInfos.Nodes[0].ID,
SlwNodeID: slwNodeInfos[0].ID,
}) })
So(err, ShouldBeNil) So(err, ShouldBeNil)
fmt.Printf("memoryData: %v\n", memoryData) fmt.Printf("memoryData: %v\n", memoryData)


indicatorData, err := cli.GetIndicatorData(GetOneResourceDataReq{ indicatorData, err := cli.GetIndicatorData(GetOneResourceDataReq{
SlwNodeID: slwNodeInfos.Nodes[0].ID,
SlwNodeID: slwNodeInfos[0].ID,
}) })
So(err, ShouldBeNil) So(err, ShouldBeNil)
fmt.Printf("indicatorData: %v\n", indicatorData) fmt.Printf("indicatorData: %v\n", indicatorData)


+ 19
- 3
utils/http/http.go View File

@@ -1,6 +1,7 @@
package http package http


import ( import (
"bytes"
"fmt" "fmt"
"io" "io"
"mime/multipart" "mime/multipart"
@@ -9,6 +10,7 @@ import (
"strings" "strings"


"gitlink.org.cn/cloudream/common/pkgs/iterator" "gitlink.org.cn/cloudream/common/pkgs/iterator"
"gitlink.org.cn/cloudream/common/utils/math"
"gitlink.org.cn/cloudream/common/utils/serder" "gitlink.org.cn/cloudream/common/utils/serder"
) )


@@ -120,7 +122,13 @@ func ParseJSONResponse[TBody any](resp *http.Response) (TBody, error) {
return ret, nil return ret, nil
} }


return ret, fmt.Errorf("unknow response content type: %s, status: %d", contType, resp.StatusCode)
cont, err := io.ReadAll(resp.Body)
if err != nil {
return ret, fmt.Errorf("unknow response content type: %s, status: %d", contType, resp.StatusCode)
}
strCont := string(cont)

return ret, fmt.Errorf("unknow response content type: %s, status: %d, body(prefix): %s", contType, resp.StatusCode, strCont[:math.Min(len(strCont), 200)])
} }


type MultiPartRequestParam struct { type MultiPartRequestParam struct {
@@ -273,7 +281,13 @@ func prepareJSONBody(req *http.Request, body any) error {
return nil return nil
} }


req.Body = serder.ObjectToJSONStream(body)
data, err := serder.ObjectToJSON(body)
if err != nil {
return err
}

req.ContentLength = int64(len(data))
req.Body = io.NopCloser(bytes.NewReader(data))
return nil return nil
} }


@@ -297,7 +311,9 @@ func prepareFormBody(req *http.Request, body any) error {
values.Add(k, fmt.Sprintf("%v", v)) values.Add(k, fmt.Sprintf("%v", v))
} }


req.Body = io.NopCloser(strings.NewReader(values.Encode()))
data := values.Encode()
req.Body = io.NopCloser(strings.NewReader(data))
req.ContentLength = int64(len(data))
return nil return nil
} }




+ 43
- 0
utils/serder/types.go View File

@@ -0,0 +1,43 @@
package serder

import (
"fmt"
"strconv"
"time"
)

type TimestampSecond time.Time

func (t *TimestampSecond) MarshalJSON() ([]byte, error) {
raw := time.Time(*t)
return []byte(fmt.Sprintf("%d", raw.Unix())), nil
}

func (t *TimestampSecond) UnmarshalJSON(data []byte) error {
var timestamp int64
var err error
if timestamp, err = strconv.ParseInt(string(data), 10, 64); err != nil {
return err
}

*t = TimestampSecond(time.Unix(timestamp, 0))
return nil
}

type TimestampMilliSecond time.Time

func (t *TimestampMilliSecond) MarshalJSON() ([]byte, error) {
raw := time.Time(*t)
return []byte(fmt.Sprintf("%d", raw.UnixMilli())), nil
}

func (t *TimestampMilliSecond) UnmarshalJSON(data []byte) error {
var timestamp int64
var err error
if timestamp, err = strconv.ParseInt(string(data), 10, 64); err != nil {
return err
}

*t = TimestampMilliSecond(time.UnixMilli(timestamp))
return nil
}

+ 35
- 0
utils/serder/types_test.go View File

@@ -0,0 +1,35 @@
package serder

import (
"encoding/json"
"testing"
"time"

. "github.com/smartystreets/goconvey/convey"
)

func Test_Timestamp(t *testing.T) {
Convey("秒级时间戳", t, func() {
str := "1698894747"

var ts TimestampSecond

err := json.Unmarshal([]byte(str), &ts)
So(err, ShouldBeNil)

t := time.Time(ts)
So(t.Unix(), ShouldEqual, 1698894747)
})

Convey("毫秒级时间戳", t, func() {
str := "1698895130651"

var ts TimestampMilliSecond

err := json.Unmarshal([]byte(str), &ts)
So(err, ShouldBeNil)

t := time.Time(ts)
So(t.UnixMilli(), ShouldEqual, 1698895130651)
})
}

Loading…
Cancel
Save