client mode

This commit is contained in:
zhouqunjie 2024-02-27 16:19:46 +08:00
parent 16ab423712
commit 4f88e9ac24
16 changed files with 574 additions and 30 deletions

87
.gitignore vendored Normal file
View File

@ -0,0 +1,87 @@
### Intellij+all template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Example user template template
### Example user template
# IntelliJ project files
.idea
*.iml
out
gen

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# pcm-hpc

4
go.mod
View File

@ -1,6 +1,6 @@
module gitlink.org.cn/zhouqunjie/pcm-slurm2
module gitlink.org.cn/JointCloud/pcm-hpc
go 1.21.7
go 1.21
require (
github.com/go-resty/resty/v2 v2.11.0

52
main.go
View File

@ -2,23 +2,61 @@ package main
import (
"fmt"
"gitlink.org.cn/zhouqunjie/pcm-slurm2/slurm"
"gitlink.org.cn/JointCloud/pcm-hpc/paratera"
"time"
)
func main() {
//slurm test
/****
start := time.Now().UnixNano() / int64(time.Millisecond)
cli, _ := slurm.NewClient(slurm.ClientOptions{
UserName: "slurmrestd",
Token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MDkwMjIzOTcsImlhdCI6MTcwOTAyMDU5Nywic3VuIjoic2x1cm1yZXN0ZCJ9.uiIPJhh4atGl99LKfpkGCz6mcutFfQnrR72FBYvYXMs",
URL: "http://192.168.249.122:6820",
RestUserName: "slurmrestd",
CmdUserName: "root",
Password: "",
Token: "",
URL: "",
AdaptMode: "rest",
ClientVersion: "v0.0.38",
})
jober, _ := cli.NewJober(slurm.JobOptions{})
jober, _ := cli.Job(slurm.JobOptions{})
result := jober.ListJob()
jobProp := slurm.JobProperties{}
opt := slurm.JobOptions{
Script: "srun sleep 200",
Job: &jobProp,
Jobs: nil,
}
result := jober.SubmitJob(opt)
str := fmt.Sprintf("%v", result)
fmt.Println(str)
end := time.Now().UnixNano() / int64(time.Millisecond)
duration := end - start
fmt.Printf("方法调用时间为 %d 毫秒\n", duration)
****/
start := time.Now().UnixNano() / int64(time.Millisecond)
cli, _ := paratera.NewClient(paratera.ClientOptions{
Url: "https://user.paratera.com",
TokenType: "TOKEN",
ThirdParty: "NMPHONE",
Phone: "",
Password: "",
})
job, _ := cli.Job(paratera.JobOptions{})
sbs := paratera.Sbs{
JobGroupName: "vasp",
JobName: "sbsjob",
SubmitProfile: paratera.SubmitProfile{
BootScript: "jobsubmit.sh",
WorkingDir: "prn:pcs:sftp:CSTC9:CSTC9:sc30314:file:/public4/home/sc56516/jobs/VNCView_20240203180350",
},
}
result := job.SubmitSbsJob(sbs)
str := fmt.Sprintf("%v", result)
fmt.Println(str)
end := time.Now().UnixNano() / int64(time.Millisecond)

19
paratera/client.go Normal file
View File

@ -0,0 +1,19 @@
package paratera
type ClientOptions struct {
Url string
TokenType string
ThirdParty string
Email string
Phone string
Password string
Token string
}
type Client interface {
Job(JobOptions) (Job, error)
Token(TokenOptions) (Token, error)
}
func NewClient(options ClientOptions) (Client, error) {
return newClient(options)
}

48
paratera/client_impl.go Normal file
View File

@ -0,0 +1,48 @@
package paratera
import "github.com/go-resty/resty/v2"
type client struct {
url string
tokenType string
thirdParty string
email string
phone string
password string
token string
}
func (c *client) Token(options TokenOptions) (Token, error) {
token, _ := newToken(c, &options)
return token, nil
}
func (c *client) Job(options JobOptions) (Job, error) {
job, _ := newJob(c, &options)
return job, nil
}
func newClient(options ClientOptions) (Client, error) {
httpClient := resty.New().R()
params := make(map[string]string)
params["token_type"] = options.TokenType
params["third_party"] = options.ThirdParty
params["email"] = options.Email
params["phone"] = options.Phone
params["password"] = options.Password
result, _ := httpClient.SetHeader("Content-Type", "x-www-form-urlencoded").
SetQueryParams(params).Post(options.Url + "/user/api/login")
c := &client{
tokenType: options.TokenType,
thirdParty: options.ThirdParty,
email: options.Email,
phone: options.Phone,
password: options.Password,
token: result.Header().Get("PARA_TOKEN"),
}
return c, nil
}

69
paratera/job.go Normal file
View File

@ -0,0 +1,69 @@
package paratera
type JobOptions struct {
sbs Sbs
abs Abs
listJobReq ListJobReq
getJobReq GetJobReq
cancelJobReq CancelJobReq
}
// Sbs 自由提交任务
type Sbs struct {
JobGroupName string `json:"jobGroupName"`
JobName string `json:"jobName"`
SubmitProfile SubmitProfile `json:"submitProfile"`
}
type SubmitProfile struct {
BootScript string `json:"bootScript"`
WorkingDir string `json:"workingDir"`
}
// Abs 模板提交任务
type Abs struct {
App string `json:"app"`
JobName string `json:"jobName"`
SubmitProfiles []SubmitProfiles `json:"submitProfiles"`
}
type AddtionalParams struct {
Key string `json:"key"`
Value string `json:"value"`
}
type SubmissionParameters struct {
AddtionalParams []AddtionalParams `json:"addtionalParams"`
Cores int `json:"cores"`
Nodes int `json:"nodes"`
}
type SubmitProfiles struct {
Queue string `json:"queue"`
SubmissionParameters SubmissionParameters `json:"submissionParameters"`
}
// ListJobReq 作业列表请求体
type ListJobReq struct {
PageSize int //分页大小
PageNo int //页码
AppCode string //应用编码
Version string //应用版本
Status string //作业状态(DONE 完成 RUN 运行 PENDING 排队 CANCEL 取消 FAIL 错误 UNKNOWN 未知)
Zone string //超算
Cluster string //集群
}
// GetJobReq 作业详情请求体
type GetJobReq struct {
jobId string //作业id
}
// CancelJobReq 作业取消请求体
type CancelJobReq struct {
jobId string //作业id
}
type Job interface {
ListJob(listJobReq ListJobReq) string
GetJob(getJobReq GetJobReq) string
SubmitSbsJob(sbs Sbs) string
SubmitAbsJob(abs Abs) string
CancelJob(cancelJobReq CancelJobReq) string
}

54
paratera/job_impl.go Normal file
View File

@ -0,0 +1,54 @@
package paratera
import (
"github.com/go-resty/resty/v2"
"log"
"sync"
)
type job struct {
sync.RWMutex
client *client
options *JobOptions
log log.Logger
}
func (j *job) ListJob(listJobReq ListJobReq) string {
//TODO implement me
panic("implement me")
}
func (j *job) GetJob(getJobReq GetJobReq) string {
//TODO implement me
panic("implement me")
}
func (j *job) SubmitSbsJob(sbs Sbs) string {
httpClient := resty.New().R()
result, _ := httpClient.SetHeader("Content-Type", "application/json").
SetHeader("para_token", j.client.token).
SetHeader("X-SLURM-USER-TOKEN", j.client.token).
Post(j.client.url + "/api/pcs/jobs/sbs")
return result.String()
}
func (j *job) SubmitAbsJob(abs Abs) string {
//TODO implement me
panic("implement me")
}
func (j *job) CancelJob(cancelJobReq CancelJobReq) string {
//TODO implement me
panic("implement me")
}
func newJob(client *client, options *JobOptions) (*job, error) {
job := &job{
RWMutex: sync.RWMutex{},
client: client,
options: options,
log: log.Logger{},
}
return job, nil
}

8
paratera/token.go Normal file
View File

@ -0,0 +1,8 @@
package paratera
type TokenOptions struct {
}
type Token interface {
GetToken(options TokenOptions) string
}

38
paratera/token_impl.go Normal file
View File

@ -0,0 +1,38 @@
package paratera
import (
"github.com/go-resty/resty/v2"
"log"
"sync"
)
type token struct {
sync.RWMutex
client *client
options *JobOptions
log log.Logger
}
func newToken(client *client, options *TokenOptions) (*token, error) {
token := &token{
RWMutex: sync.RWMutex{},
client: nil,
options: nil,
log: log.Logger{},
}
return token, nil
}
func (t *token) GetToken(options TokenOptions) string {
httpClient := resty.New().R()
params := make(map[string]string)
params["token_type"] = t.client.tokenType
params["third_party"] = t.client.thirdParty
params["email"] = t.client.email
params["phone"] = t.client.phone
params["password"] = t.client.password
result, _ := httpClient.SetHeader("Content-Type", "x-www-form-urlencoded").
SetQueryParams(params).Post(t.client.url + "/user/api/login")
return result.Header().Get("PARA_TOKEN")
}

View File

@ -1,14 +1,28 @@
package slurm
type ClientOptions struct {
UserName string
RestUserName string
CmdUserName string
Password string
Token string
URL string
AdaptMode string
ClientVersion string
}
type Client interface {
NewJober(JobOptions) (Jober, error)
Job(JobOptions) (Job, error)
Token(TokenOptions) (Token, error)
//Node(NodeOptions) (Node, error)
//Cluster(ClusterOptions) (Cluster, error)
//Partition(PartitionOptions) (Partition, error)
//Association(AssociationOptions) (Association, error)
//Account(AccountOptions) (Account, error)
//Qos(QosOptions) (Qos, error)
//Reservation(ReservationOptions) (Reservation, error)
//Tres(TresOptions) (Tres, error)
//User(UserOptions) (User, error)
//Wckey(WckeyOptions) (Wckey, error)
//Configuration(ConfigurationOptions) (Configuration, error)
}
func NewClient(options ClientOptions) (Client, error) {

View File

@ -1,21 +1,30 @@
package slurm
type client struct {
username string
restUsername string
cmdUsername string
password string
token string
url string
adaptMode string
clientVersion string
}
func (c *client) NewJober(options JobOptions) (Jober, error) {
jober, err := NewJober(c, &options)
return jober, err
func (c *client) Token(options TokenOptions) (Token, error) {
token, _ := newToken(c, &options)
return token, nil
}
func (c *client) Job(options JobOptions) (Job, error) {
job, _ := newJob(c, &options)
return job, nil
}
func newClient(options ClientOptions) (Client, error) {
c := &client{
username: options.UserName,
restUsername: options.RestUserName,
cmdUsername: options.CmdUserName,
password: options.Password,
token: options.Token,
url: options.URL,
adaptMode: options.AdaptMode,

View File

@ -1,11 +1,87 @@
package slurm
type JobOptions struct {
JobUrl string
JobSubmitUrl string
type JobProperties struct {
Account string
AccountGatherFrequency string
Argv []string
Array string
BatchFeatures string
BeginTime uint32
BurstBuffer string
ClusterConstraint string
Comment string
Constraints string
CoreSpecification uint32
CoresPerSocket uint32
CpuBinding string
CpuBindingHint string
CpuFrequency string
CpusPerGpu string
CpusPerTask uint32
CurrentWorkingDirectory string
Deadline string
DelayBoot uint32
Dependency string
Distribution string
Environment map[string]string
Exclusive string
GetUserEnvironment bool
Gres string
GresFlags string
GpuBinding string
GpuFrequency string
Gpus string
GpusPerNode string
GpusPerSocket string
GpusPerTask string
Hold bool
KillOnInvalidDependency bool
Licenses string
MailType string
MailUser string
McsLabel string
MemoryBinding string
MemoryPerCpu uint32
MemoryPerGpu uint32
MemoryPerNode uint32
MinimumCpusPerNode uint32
MinimumNodes bool
Name string
Nice string
NoKill bool
Nodes []uint32
OpenMode string
Partition string
Priority string
Qos string
Requeue bool
Reservation string
Signal string
SocketsPerNode uint32
SpreadJob bool
StandardError string
StandardInput string
StandardOutput string
Tasks uint32
TasksPerCore uint32
TasksPerNode uint32
TasksPerSocket uint32
ThreadSpecification uint32
ThreadsPerCore uint32
TimeLimit uint32
TimeMinimum uint32
WaitAllNodes bool
Wckey string
}
type Jober interface {
type JobOptions struct {
Script string
Job *JobProperties
Jobs *JobProperties
}
type Job interface {
ListJob() string
ListDbJob() string
SubmitJob(options JobOptions) string
}

View File

@ -6,38 +6,50 @@ import (
"sync"
)
type jober struct {
type job struct {
sync.RWMutex
client *client
options *JobOptions
log log.Logger
}
func NewJober(client *client, options *JobOptions) (*jober, error) {
jober := &jober{
func newJob(client *client, options *JobOptions) (*job, error) {
job := &job{
RWMutex: sync.RWMutex{},
client: nil,
options: nil,
client: client,
options: options,
log: log.Logger{},
}
return jober, nil
return job, nil
}
func (j *jober) ListJob() string {
func (j *job) ListJob() string {
httpClient := resty.New().R()
result, _ := httpClient.SetHeader("Content-Type", "application/json").
SetHeader("X-SLURM-USER-NAME", j.client.username).
SetHeader("X-SLURM-USER-NAME", j.client.restUsername).
SetHeader("X-SLURM-USER-TOKEN", j.client.token).
Get(j.client.url + "/slurm/" + j.client.clientVersion + "/jobs")
return result.String()
}
func (j *jober) SubmitJob(jobOptions JobOptions) string {
func (j *job) ListDbJob() string {
httpClient := resty.New().R()
result, _ := httpClient.SetHeader("Content-Type", "application/json").
SetHeader("X-SLURM-USER-NAME", j.client.username).
SetHeader("X-SLURM-USER-NAME", j.client.restUsername).
SetHeader("X-SLURM-USER-TOKEN", j.client.token).
Get(j.client.url + "/slurm/" + j.client.clientVersion + "/jobs")
return result.String()
}
func (j *job) SubmitJob(jobOptions JobOptions) string {
httpClient := resty.New().R()
url := j.client.url + "/slurm/" + j.client.clientVersion + "/job/submit"
result, _ := httpClient.SetHeader("Content-Type", "application/json").
SetHeader("X-SLURM-USER-NAME", j.client.restUsername).
SetHeader("X-SLURM-USER-TOKEN", j.client.token).
SetBody(jobOptions).
Post(url)
return result.String()
}

9
slurm/token.go Normal file
View File

@ -0,0 +1,9 @@
package slurm
type TokenOptions struct {
}
type Token interface {
GetToken(options TokenOptions) string
ValidateToken(options TokenOptions) bool
}

61
slurm/token_impl.go Normal file
View File

@ -0,0 +1,61 @@
package slurm
import (
"github.com/go-resty/resty/v2"
"gitlink.org.cn/JointCloud/pcm-hpc/utils"
gossh "golang.org/x/crypto/ssh"
"log"
"strings"
"sync"
)
type token struct {
sync.RWMutex
client *client
options *JobOptions
log log.Logger
}
func newToken(client *client, options *TokenOptions) (*token, error) {
token := &token{
RWMutex: sync.RWMutex{},
client: nil,
options: nil,
log: log.Logger{},
}
return token, nil
}
func (t *token) GetToken(options TokenOptions) string {
cli := utils.Cli{
Addr: t.client.url,
User: t.client.cmdUsername,
Pwd: t.client.password,
}
// 建立连接对象
cl, _ := cli.Connect()
// 退出时关闭连接
defer func(Client *gossh.Client) {
err := Client.Close()
if err != nil {
}
}(cl.Client)
res, _ := cl.Run(`scontrol token username=slurmrestd lifespan=10000`)
arr := strings.Split(res, "=")
t.client.token = strings.Replace(arr[1], "\n", "", -1)
return t.client.token
}
func (t *token) ValidateToken(options TokenOptions) bool {
httpClient := resty.New().R()
result, _ := httpClient.SetHeader("Content-Type", "application/json").
SetHeader("X-SLURM-USER-NAME", t.client.restUsername).
SetHeader("X-SLURM-USER-TOKEN", t.client.token).Get(t.client.url + "/slurm/" + t.client.clientVersion + "/ping")
if len(result.String()) > 0 {
return true
} else {
return false
}
}