Merge Go frontend (apiserver + xcecli) into meson build

This commit is contained in:
Rongsong Shen 2026-04-14 11:20:17 +08:00
parent 43dc12a36c
commit c9dc8c4676
205 changed files with 30793 additions and 328 deletions

View file

@ -0,0 +1,18 @@
package models
import "time"
type APIKeyController struct{}
type APIKeyRequest struct {
Username string `json:"username" binding:"required"`
Description string `json:"description,omitempty"`
ExpiryDays int `json:"expiry_days,omitempty"`
}
type APIKeyResponse struct {
APIKey string `json:"api_key"`
Username string `json:"username"`
CreateTime time.Time `json:"create_time"`
ExpiryTime time.Time `json:"expiry_time"`
}

View file

@ -0,0 +1,37 @@
package models
import (
"github.com/golang-jwt/jwt/v4"
)
type LogonRequest struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
}
type LogoutRequest struct {
Username string `json:"username" binding:"required"`
}
type JWTClaims struct {
Username string `json:"username"`
IP string `json:"ip"`
jwt.RegisteredClaims
}
type LogonResponse struct {
Token string `json:"token"`
Path string `json:"path"`
IP string `json:"ip"`
TokenExpireTime int `json:"token_expire_time"`
}
type LogoutResponse struct {
Username string `json:"username"`
Message string `json:"message"`
}
type User struct {
Username string `json:"username"`
Password string `json:"password"`
}

View file

@ -0,0 +1,45 @@
package models
const (
CLUSTER_RECONFIG = 1
CLUSTER_RESTART = 2
CLUSTER_SHUTDOWN = 3
)
var CLUSTERSTAT = map[string]int{
"DISCONNECT": 0x0,
"CONNECTED": 0x01,
}
var JSONBCLFields = []string{"resources", "host_types", "host_models", "cluster_admins"}
type ClusterInfo struct {
ClusterName string `json:"cluster_name"`
Version string `json:"version"`
Status int `json:"status"`
ControllerName string `json:"controller_name"`
NumServers int `json:"num_servers"`
Resources string `json:"resources"`
HostTypes string `json:"host_types"`
HostModels string `json:"host_models"`
ClusterAdmins string `json:"cluster_admins"`
}
var CLUSTER_SUPPORT_FILTERS = []string{
"cluster_name",
}
var CLUSTER_DEFAULT_COLUMN = []string{
"cluster_name",
"version",
"status",
"controller_name",
"resources",
"host_types",
"host_models",
"cluster_admins",
}
var CLUSTER_SUPPORT_SORT = []string{
"cluster_name",
}

View file

@ -0,0 +1,19 @@
package models
import "time"
const (
CONTROL_JOB = 1
CONTROL_HOST = 2
CONTROL_QUEUE = 3
CONTROL_CLUSTER = 4
CONTROL_DEBUG = 5
)
type ActionControl struct {
TargetType int `json:"target_type"`
ActionType int `json:"action_type"`
Content Jsonb `json:"content"`
SubmitTime time.Time `json:"submit_time"`
Submitter string `json:"submitter"`
}

View file

@ -0,0 +1,7 @@
package models
type FileUploadRequest struct {
InFile string `json:"in_file" binding:"required"`
}
var SupportedFileParams = []string{"path"}

View file

@ -0,0 +1,134 @@
package models
const (
HOST_OPEN = 1
HOST_CLOSE = 2
HOST_TAG = 3
HOST_UNTAG = 4
)
var SupportedHostActions = []string{"open", "close"}
var HOSTSTAT = map[string]int{
"UNAVAIL": 0x00010000,
"LOCKEDU": 0x00020000,
"LOCKEDW": 0x00040000,
"BUSY": 0x00080000,
"CLOSED": 0x00100000,
}
func HostStateStr(state int) string {
if (state & HOSTSTAT["UNAVAIL"]) != 0 {
return "UNAVAIL"
} else if (state & HOSTSTAT["CLOSED"]) != 0 {
return "CLOSED"
} else if (state & HOSTSTAT["BUSY"]) != 0 {
return "BUSY"
} else if (state & HOSTSTAT["LOCKEDU"]) != 0 {
return "LOCKU"
} else if (state & HOSTSTAT["LOCKEDW"]) != 0 {
return "LOCKW"
}
return "OK"
}
// JSONBFields contains the list of fields that are in JSONB format
var JSONBHFields = []string{"topology", "sched_stop", "real_load", "dispt_window"}
var HOST_DEFAULT_COLUMN = []string{
"host_name",
//"ip_addr", // not supported yet
"host_status",
"host_model",
"host_type",
"host_group",
"flag",
"cpu_factor",
"num_cpus",
"num_cores",
"num_threads",
"dispt_window",
"max_slot",
"max_mem",
"max_swap",
"max_tmp",
"num_disk",
"num_run",
"num_ssusp",
"num_ususp",
//"num_rsv",
"num_done",
"topology",
"sched_stop",
//"real_load",
}
type HostInfo struct {
HostID int64 `json:"host_id"`
HostName string `json:"host_name"`
HostStatus int `json:"host_status"`
HostModel string `json:"host_model"`
HostType string `json:"host_type"`
HostGroup string `json:"host_group"`
Flag int `json:"flag"`
CPUFactor float64 `json:"cpu_factor"`
DisptWindow string `json:"dispt_window"`
NumCPUs int `json:"num_cpus"`
NumCores int `json:"num_cores"`
NumThreads int `json:"num_threads"`
MaxSlot int `json:"max_slot"`
MaxMem int `json:"max_mem"`
MaxSwap int `json:"max_swap"`
MaxTmp int `json:"max_tmp"`
NumDisk int `json:"num_disk"`
NumRun int `json:"num_run"`
NumSSusp int `json:"num_ssusp"`
NumUSusp int `json:"num_ususp"`
//NumRsv int `json:"num_rsv"`
NumDone int `json:"num_done"`
Topology string `json:"topology"` // JSONB
SchedStop string `json:"sched_stop"` // JSONB
//RealLoad string `json:"real_load"` // JSONB
}
// host info query supported filter
var HOST_SUPPORT_FILTERS = []string{
"host_name",
"host_model",
"host_type",
"host_group",
"flag",
"cpu_factor",
"num_cpus",
"max_slot",
"max_mem",
"max_swap",
"max_tmp",
"num_disk",
"num_run",
"num_ssusp",
"num_ususp",
//"num_rsv",
"num_done",
}
var HOST_SUPPORT_SORT = []string{
"host_name",
}
type HostControlRequest struct {
ControlAction string `json:"action" binding:"required"`
Hostname []string `json:"host_name" binding:"required"`
Comment string `json:"comment"`
}
type ResReqSelectRequest struct {
Select string `json:"select" binding:"required"`
Order string `json:"order,omitempty"`
Limit int `json:"limit,omitempty"`
Pagetoken string `json:"page_token,omitempty"`
}
type HostControlEvent struct {
Hostname string `json:"host_name" binding:"required"`
Comment string `json:"comment,omitempty"`
}

View file

@ -0,0 +1,756 @@
package models
import (
"encoding/json"
"errors"
"fmt"
"strconv"
"strings"
"time"
)
const RLIM_NLIMITS = 12
const (
JOB_STOP = 1
JOB_RESUME = 2
JOB_KILL = 3
JOB_MIG = 4
JOB_REQUEUE = 5
JOB_MODIFY = 6
JOB_SWITCH = 7
JOB_CHKPNT = 8
JOB_POST = 9
JOB_READ = 10
JOB_TOP = 11
JOB_BOT = 12
)
var JobSignalMapTable = map[string]int{
"HUP": 1, // Hangup
"INT": 2, // Interrupt
"QUIT": 3, // Quit
"ILL": 4, // Illegal instruction
"TRAP": 5, // Trace trap
"ABRT": 6, // ABRT instruction
"BUS": 7, // Bus error
"FPE": 8, // Floating point exception
"KILL": 9, // Kill (cannot be caught or ignored)
"USR1": 10, // User-defined signal 1
"SEGV": 11, // Segmentation violation
"USR2": 12, // User-defined signal 2
"PIPE": 13, // Write on a pipe with no one to read it
"ALRM": 14, // Alarm clock
"TERM": 15, // Termination signal
"STKFLT": 16, // Stack fault (historical, often unused or same as SEGV)
"CHLD": 17, // Child process terminated, stopped, or continued
"CONT": 18, // Continue executing, if stopped
"STOP": 19, // Stop executing (cannot be caught or ignored)
"TSTP": 20, // Terminal stop signal
"TTIN": 21, // Background process attempting read
"TTOU": 22, // Background process attempting write
"URG": 23, // Urgent condition (often unused or same as PWR)
"XCPU": 24, // CPU time limit exceeded
"XFSZ": 25, // File size limit exceeded
"VTALRM": 26, // Virtual timer expired
"PROF": 27, // Profiling timer expired
"WINCH": 28, // Window changed
"IO": 29, // I/O possible (often same as POLL)
"PWR": 30, // Power failure (historical, often unused or same as USR1)
"SYS": 31, // Bad system call (historical, often unused or same as USR2)
}
var JOBSTAT = map[string]int{
"PEND": 0x01,
"RUN": 0x02,
"EXIT": 0x04,
"DONE": 0x08,
"PSUSP": 0x10,
"USUSP": 0x20,
"SSUSP": 0x40,
"PDONE": 0x80,
"PERR": 0x100,
"RUNKWN": 0x8000,
"UNKNOWN": 0x1000,
}
var LAUNCHTYPE = map[string]int{
"openmpi": 1,
"mpich": 2,
}
func JobStateStr(state int) string {
if (state & JOBSTAT["PEND"]) != 0 {
if (state & JOBSTAT["PSUSP"]) != 0 {
return "PSUSP"
}
return "PEND"
} else if (state & JOBSTAT["RUN"]) != 0 {
if (state & JOBSTAT["USUSP"]) != 0 {
return "USUSP"
} else if (state & JOBSTAT["SSUSP"]) != 0 {
return "SSUSP"
}
return "RUN"
} else if (state & JOBSTAT["EXIT"]) != 0 {
return "EXIT"
} else if (state & JOBSTAT["DONE"]) != 0 {
return "DONE"
}
return "ERR"
}
var SupportedJobActions = []string{"kill", "stop", "resume", "checkpoint"}
var ValidInteractiveValues = []string{"0", "1", "2", "3"}
var ValidLaunchTypes = []string{"openmpi", "mpich"}
var JobActionControlMap = map[int][]int{
JOB_CHKPNT: {JOBSTAT["RUN"]},
JOB_STOP: {JOBSTAT["RUN"], JOBSTAT["PEND"]},
JOB_RESUME: {JOBSTAT["USUSP"], JOBSTAT["PSUSP"]},
JOB_KILL: {JOBSTAT["RUN"], JOBSTAT["PEND"], JOBSTAT["SSUSP"], JOBSTAT["USUSP"], JOBSTAT["PSUSP"], JOBSTAT["UNKNOWN"]},
}
var JobKillSignalControlMap = map[int][]int{
JOB_KILL: {JOBSTAT["RUN"], JOBSTAT["PEND"], JOBSTAT["SSUSP"], JOBSTAT["USUSP"], JOBSTAT["PSUSP"]},
}
var DefaultActionSignal = map[string]string{
"kill": "TERM",
"stop": "TSTP",
"resume": "CONT",
}
var JobAvailableTypes = []string{"array_stats"}
// JSONBFields contains the list of fields that are in JSONB format
var JSONBJFields = []string{
"exec_hosts",
"sub_env_vars",
"pending_reason",
"job_rusage",
"license_names",
"submit_ext",
"extend_data",
"tags",
"exit_status",
"pid_info",
"transfer_files",
"pids",
"pgids",
}
var ARRAY_JOB_SUPPORT_FILTERS = []string{
"job_id",
"submit_user",
"queue_name",
"job_description",
"job_name",
//"user_group",
//"job_group",
//"project_name",
//"license_project",
//"sla",
}
// job info query supported filter
var JOB_SUPPORT_FILTERS = []string{
"submit_user",
"queue_name",
"job_status",
"array_idx",
"exec_hosts", // may be []string
"job_description",
"job_name",
"job_id",
//"user_group",
//"job_group",
//"project_name",
//"license_project",
//"sla",
"submit_time",
"queue_time",
"start_time",
"end_time",
"reserve_time",
}
var JOB_SUPPORT_SORT = []string{
"job_id",
"job_status",
"queue_name",
"submit_time",
"submit_user",
}
// when query jobinfo, the default display columns.
var JOB_DEFAULT_COLUMN = []string{
"job_id",
"array_idx",
"unique_job_id",
"submit_user",
"job_status",
"queue_name",
"from_host",
"exec_hosts",
"job_name",
"command",
"submit_time",
}
var ARRAY_JOB_DEFAULT_COLUMN = []string{
"job_id",
"array_job_name",
"submit_user",
"queue_name",
"user_group",
"job_group",
"job_description",
"job_name",
"project_name",
"license_project",
"sla",
"num_jobs",
"num_done",
"num_exit",
"num_run",
"num_pend",
"num_ssusp",
"num_ususp",
"num_psusp",
}
type JobArrayID struct {
ArrayIdx int `json:"array_idx"`
Unique_JobID int64 `json:"job_id"`
}
type CustomTime struct {
Time time.Time
}
type CustomInt struct {
Seconds int
}
type Jsonb struct {
String string
}
type TimeStamp struct {
TimeStamp int64
}
func (jsb *Jsonb) IsZero() bool {
return jsb.String == ""
}
func (tm *CustomTime) Tm() time.Time {
return tm.Time
}
type CustomLimit struct {
MB float64
}
func (cl *CustomLimit) String() string {
switch {
case cl.MB >= 1<<30:
return fmt.Sprintf("%.2f PB", cl.MB/(1<<30))
case cl.MB >= 1<<20:
return fmt.Sprintf("%.2f TB", cl.MB/(1<<20))
case cl.MB >= 1<<10:
return fmt.Sprintf("%.2f GB", cl.MB/(1<<10))
default:
return fmt.Sprintf("%.2f MB", cl.MB)
}
}
func (cl *CustomLimit) UnmarshalJSON(b []byte) error {
s := strings.Trim(string(b), "\"")
if s == "null" || s == "" {
cl.MB = 0
return nil
}
// Expecting format like "1024 MB", "1 GB", etc.
parts := strings.Split(s, " ")
if len(parts) != 1 && len(parts) != 2 {
return fmt.Errorf("invalid limit format, expected '<number> <unit>'")
}
value, err := strconv.ParseFloat(parts[0], 64)
if err != nil {
return fmt.Errorf("invalid limit format, expected '<number> <unit>'")
}
unit := "MB"
if len(parts) == 2 && parts[1] != "" {
unit = strings.ToUpper(parts[1])
}
switch unit {
case "MB", "M":
cl.MB = value
case "GB", "G":
cl.MB = value * 1024
case "TB", "T":
cl.MB = value * 1024 * 1024
case "PB", "P":
cl.MB = value * 1024 * 1024 * 1024
default:
return fmt.Errorf("unsupported unit: %s", unit)
}
return nil
}
func (sl *ShellLimit) UnmarshalJSON(b []byte) error {
type Alias ShellLimit
aux := &struct {
*Alias
}{
Alias: (*Alias)(sl),
}
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
limits := []*CustomLimit{
&sl.FileLimit,
&sl.DataLimit,
&sl.StackLimit,
&sl.CoreLimit,
&sl.ProcessLimit,
&sl.ThreadLimit,
&sl.MemLimit,
&sl.SwapLimit,
}
for _, limit := range limits {
if limit != nil {
if err := limit.UnmarshalJSON([]byte(limit.String())); err != nil {
return err
}
}
}
return nil
}
func (tm *CustomTime) IsZero() bool {
return tm.Time.IsZero()
}
func (ci *CustomInt) String() string {
hours := ci.Seconds / 3600
minutes := (ci.Seconds % 3600) / 60
return fmt.Sprintf("%d:%02d", hours, minutes)
}
func (ci *CustomInt) Int() int {
return ci.Seconds
}
func (ci *CustomInt) Float64() float64 {
return float64(ci.Seconds)
}
func (ci *CustomInt) UnmarshalJSON(b []byte) error {
var hours, minutes int
var err error
s := strings.Trim(string(b), "\"")
if s == "null" || s == "" {
ci.Seconds = 0
return nil
}
// If the input is already in seconds format
if !strings.Contains(s, ":") {
minutes, err = strconv.Atoi(s)
if err != nil {
return fmt.Errorf("invalid minutes value: %v", err)
}
ci.Seconds = minutes * 60
return nil
}
// Handle hours:minutes format
parts := strings.Split(s, ":")
if len(parts) == 2 {
hours, err = strconv.Atoi(parts[0])
if err != nil || hours < 0 || hours > 24 {
return errors.New("hour must be between 0 and 24")
}
if hours == 24 && parts[1] != "00" {
return errors.New("hour must be between 0 and 24, and minute must be 00")
}
minutes, err = strconv.Atoi(parts[1])
} else {
minutes, err = strconv.Atoi(parts[0])
}
if err != nil || (hours != 0 && (minutes < 0 || minutes > 59)) {
return errors.New("minute must be between 0 and 59")
}
ci.Seconds = hours*3600 + minutes*60
if ci.Seconds > 2147483647 {
return errors.New("limit exceeds the value of 2147483647")
}
return nil
}
// UnmarshalJSON handle time.time format data
func (ct *CustomTime) UnmarshalJSON(b []byte) error {
s := strings.Trim(string(b), "\"")
if s == "null" || s == "" {
ct.Time = time.Time{}
return nil
}
// support multiple date formats
formats := []string{
"2006-01-02 15:04:05 MST",
"2006-01-02 15:04:05",
"2006-01-02 15:04 MST",
"2006-01-02 15:04",
//"2006-01-02",
//"15:04",
}
var lastErr error
for _, format := range formats {
t, err := time.Parse(format, s)
if err == nil {
// If only time is provided (format "15:04"), use current date
/*
if format == "15:04" {
now := time.Now()
t = time.Date(now.Year(), now.Month(),
now.Day(), t.Hour(), t.Minute(), 0, 0, time.Local)
}
*/
// change time into minute level
ct.Time = t.Truncate(time.Minute)
return nil
}
lastErr = err
}
return fmt.Errorf("cannot parse time string: %s, last error: %v", s, lastErr)
}
// JRusage represents job resource usage information
// TODO: need determine
type JRusage struct {
Mem int64 `json:"mem"`
Swap int64 `json:"swap"`
Utime int64 `json:"utime"`
Stime int64 `json:"stime"`
NPgids int `json:"npgids"`
Pgid []int `json:"pgid"`
NThreads int `json:"nthreads"`
CpuUT float32 `json:"cpuUT"`
IO int64 `json:"io"`
IORate float32 `json:"iorate"`
DiskIO int64 `json:"diskio"`
DiskIORate float32 `json:"diskiorate"`
}
var JobFieldMappings = map[string]string{
// "user_used": "db_filed_name",
"file_limit": "fsize_limit",
"mem_limit": "rss_limit",
"num_files": "nofile_limit",
"env": "sub_env_vars",
// more fields can be added here
}
type JobInfo struct {
Unique_JobID int64 `json:"unique_job_id"`
JobID int64 `json:"job_id"`
ArrayIdx int `json:"array_idx"` //new
SubmitUser string `json:"submit_user"`
FromHost string `json:"from_host"`
SubmitTime time.Time `json:"submit_time"`
JobStatus int `json:"job_status"`
JobName string `json:"job_name"`
Command string `json:"command"`
QueueName string `json:"queue_name"`
ProjectName string `json:"project_name"`
JobGroup string `json:"job_group"` // new
UserGroup string `json:"user_group"`
LicenseProject string `json:"license_project"`
LicenseNames Jsonb `json:"license_names"` // JSONB as []byte
JobDescription string `json:"job_description"`
ResReq string `json:"resreq"`
RsvID string `json:"rsv_id"`
SLA string `json:"sla"`
MaxNumProcessors int `json:"maxnum_processors"`
NumProcessors int `json:"num_processors"`
AskedHosts string `json:"asked_hosts"`
LaunchType string `json:"launch_type"`
BeginTime CustomTime `json:"begin_time"` // CustomTime
TermTime CustomTime `json:"term_time"` // CustomTime
UserPriority int `json:"user_priority"`
DependCond string `json:"depend_cond"`
Umask int `json:"umask"`
CWD string `json:"cwd"`
SubmitHomeDir string `json:"submit_home_dir"`
JobPriority int `json:"job_priority"`
PreExecCmd string `json:"pre_exec_cmd"`
PostExecCmd string `json:"post_exec_cmd"`
MigThreshold int `json:"mig_threshold"`
ChkpntPeriod int `json:"chkpnt_period"`
ChkpntDir string `json:"chkpnt_dir"`
ChkpntInfo Jsonb `json:"chkpnt_info"` // JSONB as []byte
OutDir string `json:"out_dir"`
InFile string `json:"in_file"`
OutFile string `json:"out_file"`
ErrFile string `json:"err_file"`
LoginShell string `json:"login_shell"`
ExceptList string `json:"except_list"`
MailUser string `json:"mail_user"`
RequeueErrorValues string `json:"requeue_error_values"`
GPUResReq string `json:"gpu_resreq"`
SubmitExt Jsonb `json:"submit_ext"` // new, JSONB as []byte
ExtendData Jsonb `json:"extend_data"` // new, JSONB as []byte
Tags Jsonb `json:"tags"` // new, JSONB as []byte
EffectiveResReq string `json:"effective_resreq"` //new
EffectiveUserGroup string `json:"effective_user_group"` //new
QueueTime time.Time `json:"queue_time"`
StartTime time.Time `json:"start_time"`
EndTime time.Time `json:"end_time"`
ReserveTime time.Time `json:"reserve_time"`
Duration int `json:"duration"`
CPUTime int `json:"cpu_time"`
ExitStatus Jsonb `json:"exit_status"` //change type, JSONB as []byte
ExecHosts Jsonb `json:"exec_hosts"` //change type, JSONB as []byte
ExecUID int `json:"exec_uid"`
ExecHome string `json:"exec_home"`
ExecCWD string `json:"exec_cwd"`
ExecUser string `json:"exec_user"` //name change
ChargedSaap string `json:"charged_saap"`
RunTime int `json:"run_time"`
RunTimeEstimation int `json:"run_time_estimation"`
PendingReason Jsonb `json:"pending_reason"` //change type, JSONB as []byte
PIDInfo Jsonb `json:"pid_info"` // JSONB as []byte
JobRusage Jsonb `json:"job_rusage"` // JSONB as []byte
}
type JobExecHosts struct {
InsertSeq int64 `json:"insert_seq"`
HostName string `json:"host_name"`
UniqueJobID int64 `json:"unique_job_id"`
SlotNum int `json:"slot_num"`
JobStatus int `json:"job_status"`
}
type ArrayJobInfo struct {
JobID int64 `json:"job_id"`
ArrayJobName string `json:"array_job_name"`
SubmitUser string `json:"submit_user"`
QueueName string `json:"queue_name"`
UserGroup string `json:"user_group"`
JobGroup string `json:"job_group"`
JobDescription string `json:"job_description"`
JobName string `json:"job_name"`
ProjectName string `json:"project_name"`
LicenseProject string `json:"license_project"`
SLA string `json:"sla"`
NumJobs int `json:"num_jobs"`
NumDone int `json:"num_done"`
NumExit int `json:"num_exit"`
NumRun int `json:"num_run"`
NumPend int `json:"num_pend"`
NumSSusp int `json:"num_ssusp"`
NumUSusp int `json:"num_ususp"`
NumPSusp int `json:"num_psusp"`
}
type JobAdditionalFields struct {
JobID int64 `json:"job_id"`
SubmitUser string `json:"submit_user"`
JobStatus int `json:"job_status"`
SubmitTime time.Time `json:"submit_time"`
FromHost string `json:"from_host"`
ExecHosts string `json:"exec_hosts"`
StartTime time.Time `json:"start_time"`
EndTime time.Time `json:"end_time"`
JobRusage Jsonb `json:"job_rusage"`
MaxMem float64 `json:"max_mem"`
AvgMem float64 `json:"avg_mem"`
UsedMem float64 `json:"used_mem"`
CPUTime int `json:"cpu_time"`
PeakCPUTime int `json:"peak_cpu_time"`
PeakCPUDuration float64 `json:"peak_cpu_duration"`
MemEfficiency float64 `json:"mem_efficiency"` // Memory efficiency in percentage
AvgCPUEfficiency float64 `json:"avg_cpu_efficiency"` // Average CPU efficiency in percentage
PeakCPUEfficiency float64 `json:"peak_cpu_efficiency"` // Peak CPU efficiency in percentage
NumHosts int `json:"num_hosts"` // Number of hosts used by the job
FirstHost string `json:"first_host"` // First host where the job ran
AllocSlot string `json:"alloc_slots"` // Allocated slot information
PIDInfo Jsonb `json:"pid_info"`
Pids []int `json:"pids"` // List of process IDs associated with the job
Pgids []int `json:"pgids"` // List of process group IDs associated with the job
InteractiveJobURL string `json:"interactive_job_url"`
}
type JobSubmitRequest struct {
JobName string `json:"job_name,omitempty" `
Command string `json:"command" binding:"required"`
QueueName string `json:"queue_name,omitempty"` // set to DEFAULT_QUEUE in config
ProjectName string `json:"project_name,omitempty"` // default project: "default"
UserGroup string `json:"user_group,omitempty"`
LicenseProject string `json:"license_project,omitempty"`
JobDescription string `json:"job_description,omitempty"`
Resreq string `json:"resreq,omitempty"` // default: "type == local"
Affinity string `json:"affinity,omitempty"`
Gpureq string `json:"gpureq,omitempty"`
RsvID string `json:"rsv_id,omitempty"`
SLA string `json:"sla,omitempty"`
MaxNumProcessors int `json:"maxnum_processors,omitempty"`
NumProcessors int `json:"num_processors,omitempty"`
AskedHosts string `json:"asked_hosts,omitempty"`
LaunchType string `json:"launch_type,omitempty"`
BeginTime CustomTime `json:"begin_time,omitempty"` //k change type
TermTime CustomTime `json:"term_time,omitempty"` //k change type
JobPriority int `json:"job_priority,omitempty"`
DependCond string `json:"depend_cond,omitempty"`
JobGroup string `json:"job_group,omitempty"`
HostSpec string `json:"host_spec,omitempty"`
Env []string `json:"env,omitempty"`
Tags []string `json:"tags,omitempty"`
Exclusive bool `json:"exclusive,omitempty"`
Rerunable bool `json:"rerunable,omitempty"`
Interactive int `json:"interactive,omitempty"`
WarningTimePeriod int `json:"warning_time_period,omitempty"`
WarningAction string `json:"warning_action,omitempty"`
DataSpecFile string `json:"data_spec_file,omitempty"`
TransferFiles []string `json:"transfer_files,omitempty"`
PreExecCmd string `json:"pre_exec_cmd,omitempty"`
PostExecCmd string `json:"post_exec_cmd,omitempty"`
RequeueErrorValues string `json:"requeue_error_values,omitempty"`
RunTimeEstimation int `json:"run_time_estimation,omitempty"`
MigThreshold int `json:"mig_threshold,omitempty"`
ChkpntPeriod int `json:"chkpnt_period,omitempty"`
ChkpntDir string `json:"chkpnt_dir,omitempty"`
InitChkpntPeriod int `json:"init_chkpnt_period,omitempty"`
CWD string `json:"cwd,omitempty"`
OutDir string `json:"out_dir,omitempty"`
InFile string `json:"in_file,omitempty"`
OutFile string `json:"out_file,omitempty"`
ErrFile string `json:"err_file,omitempty"`
Mailuser string `json:"mailuser,omitempty"`
LoginShell string `json:"login_shell,omitempty"`
ExceptList string `json:"except_list,omitempty"`
CPULimit CustomInt `json:"cpu_limit,omitempty"` // k change type
RunLimit CustomInt `json:"run_limit,omitempty"` //k change type
FileLimit CustomLimit `json:"file_limit,omitempty"` // fsize
DataLimit CustomLimit `json:"data_limit,omitempty"`
StackLimit CustomLimit `json:"stack_limit,omitempty"`
CoreLimit CustomLimit `json:"core_limit,omitempty"`
MemLimit CustomLimit `json:"mem_limit,omitempty"`
NumFiles int `json:"num_files,omitempty"`
SwapLimit CustomLimit `json:"swap_limit,omitempty"`
ProcessLimit CustomLimit `json:"process_limit,omitempty"`
ThreadLimit CustomLimit `json:"thread_limit,omitempty"`
ShellLimit ShellLimit `json:"shell_limit,omitempty"`
ExtendData string `json:"extend_data,omitempty"`
}
type JobRestartRequest struct {
AskedHosts string `json:"asked_hosts,omitempty"`
}
type ShellLimit struct {
CPULimit int `json:"cpu_limit,omitempty"` // in milliseconds
FileLimit CustomLimit `json:"file_limit,omitempty"`
DataLimit CustomLimit `json:"data_limit,omitempty"`
StackLimit CustomLimit `json:"stack_limit,omitempty"`
CoreLimit CustomLimit `json:"core_limit,omitempty"`
ProcessLimit CustomLimit `json:"process_limit,omitempty"`
ThreadLimit CustomLimit `json:"thread_limit,omitempty"`
MemLimit CustomLimit `json:"mem_limit,omitempty"`
SwapLimit CustomLimit `json:"swap_limit,omitempty"`
NumFiles int `json:"num_files,omitempty"`
}
type JobSubmitResponse struct {
JobID int64 `json:"jobid"`
QueueName string `json:"queue_name"`
Message string `json:"message"`
}
// Job query struct in C lib
// TODO: need consider more filter conditions and "0"(means all satisfied jobs)
type JobQueryFilters struct {
Submit_user string `json:"submit_user,omitempty"`
Queue_name string `json:"queue_name,omitempty"`
User_group string `json:"user_group,omitempty"`
Job_status int `json:"job_status,omitempty"`
Exec_hosts string `json:"exec_hosts,omitempty"`
Job_name string `json:"job_name,omitempty"`
Job_group string `json:"job_group,omitempty"`
Project_name string `json:"project_name,omitempty"`
License_project string `json:"license_project,omitempty"`
Job_id int64 `json:"job_id,omitempty"`
}
type JobIndex struct {
Index string // e.g., "1-3"
Step int // Step for the range
}
type JobArrayInfo struct {
KeyID string // e.g., "316499657728"
Indices []JobIndex // List of indices with steps
}
// ------- job control -------------
type JobControlFilter struct {
JobName string `json:"job_name,omitempty"`
JobGroupName string `json:"job_group_name,omitempty"`
QueueName string `json:"queue_name,omitempty"`
Users string `json:"users,omitempty"`
ExecHosts string `json:"exec_hosts,omitempty"`
SLA string `json:"sla,omitempty"`
AllJobs bool `json:"all_jobs,omitempty"`
}
type JobControlRequest struct {
Filter JobControlFilter `json:"filter" binding:"required"`
Action string `json:"action" binding:"required"`
Signal string `json:"signal,omitempty"`
Comment string `json:"comment,omitempty"`
ForceKill bool `json:"force_kill,omitempty"`
Method string `json:"method,omitempty"` // "criu" as default
}
type JobControlJobIDRequest struct {
Action string `json:"action" binding:"required"`
Signal string `json:"signal,omitempty"` // signal value
Comment string `json:"comment,omitempty"`
ForceKill bool `json:"force_kill,omitempty"`
Method string `json:"method,omitempty"` // "criu" as default
}
type JobControlEvent struct {
UniqueJobID int64 `json:"unique_job_id" binding:"required"`
Signal int `json:"signal,omitempty"` // signal value
Comment string `json:"comment,omitempty"`
ForceKill bool `json:"force_kill,omitempty"`
Method string `json:"method,omitempty"` // "criu" as default
}
var launchTypeReverse map[int]string
func init() {
launchTypeReverse = make(map[int]string, len(LAUNCHTYPE))
for k, v := range LAUNCHTYPE {
launchTypeReverse[v] = k
}
}
func GetLaunchTypeString(code int) (string, bool) {
str, exists := launchTypeReverse[code]
return str, exists
}

View file

@ -0,0 +1,82 @@
package models
const (
QUEUE_OPEN = 1
QUEUE_CLOSE = 2
QUEUE_INACT = 3
QUEUE_ACT = 4
)
var SupportedQueueActions = []string{"open", "close", "deactive", "active"}
var ActionMap = map[string]int{
"close": QUEUE_CLOSE,
"open": QUEUE_OPEN,
"active": QUEUE_ACT,
"deactive": QUEUE_INACT,
}
// queues info query supported filter
var QUEUE_SUPPORT_FILTERS = []string{
"queue_name",
"priority",
"description",
"num_pend",
"num_run",
"num_ssusp",
"num_ususp",
"num_done",
}
var QUEUE_SUPPORT_SORT = []string{
"queue_name",
}
var QUEUESTAT = map[string]int{
"OPEN": 0x00,
"CLOSED": 0x01,
"INACTIVE_WIN": 0x02,
"INACTIVE_ADM": 0x04,
"NOPERM": 0x08,
"DISC": 0x10,
"FAIRSHARE_DEFAULT": 0x20,
}
// JSONBFields contains the list of fields that are in JSONB format
var JSONBQFields = []string{"fs_info"}
var QUEUE_DEFAULT_COLUMN = []string{
"queue_name",
"queue_status",
"priority",
"description",
"num_pend",
"num_run",
"num_ssusp",
"num_ususp",
"num_done",
"fs_info",
}
type QueueInfo struct {
QueueName string `json:"queue_name"`
QueueStatus int `json:"queue_status"`
Priority int `json:"priority"`
Description string `json:"description"`
NumPend int `json:"num_pend"`
NumRun int `json:"num_run"`
NumSSusp int `json:"num_ssusp"`
NumUSusp int `json:"num_ususp"`
NumDone int `json:"num_done"`
FSInfo string `json:"fs_info"` // JSONB
}
type QueueControlRequest struct {
ControlAction string `json:"action" binding:"required"`
QueueName []string `json:"queue_name" binding:"required"`
Comment string `json:"comment"`
}
type QueueControlEvent struct {
Queuename string `json:"queue_name" binding:"required"`
Comment string `json:"comment,omitempty"`
}

View file

@ -0,0 +1,139 @@
package models
type ValueType int
const (
STRING ValueType = iota // Bool value
NUMERIC // Numeric value
BOOLEAN // String value
)
// String returns the string representation of ValueType
func (v ValueType) String() string {
switch v {
case BOOLEAN:
return "Boolean"
case NUMERIC:
return "Numeric"
case STRING:
return "String"
default:
return "Unknown"
}
}
type OrderType int
const (
INCR OrderType = iota
DECR
NA
)
// String returns the string representation of OrderType
func (o OrderType) String() string {
switch o {
case INCR:
return "Incr"
case DECR:
return "Decr"
case NA:
return "NA"
default:
return "Unknown"
}
}
var RESOURCE_DEFAULT_COLUMN = []string{
"res_name",
"description",
"value_type",
"order_type",
"flag",
"interval",
}
var RESOURCE_DISTRIBUTION_DEFAULT_COLUMN = []string{
"res_name",
"numeric_value",
"location",
"is_dynamic",
}
var RESOURCE_DEFINITION_DEFAULT_COLUMN = []string{
"res_name",
"description",
"value_type",
"order_type",
"flag",
"interval",
}
var ResourceFieldMappings = map[string]string{
// API field name → struct field name
"value": "numeric_value",
}
var ResourcesAvailableTypes = []string{"static", "dynamic"}
const (
BUILTIN = 0x01
DYNAMIC = 0x02
RELEASE = 0x20
CONSUMABLE = 0x80
)
type FlagValue int
// ToJSON returns the JSON object representation of FlagValue
func (f FlagValue) ToJSON() map[string]bool {
return map[string]bool{
"builtin": f&BUILTIN != 0,
"dynamic": f&DYNAMIC != 0,
"release": f&RELEASE != 0,
"consumable": f&CONSUMABLE != 0,
}
}
type ResourceInfo struct {
ResName string
Description string
ValueType ValueType
OrderType OrderType
Flag int
Interval int
}
// queues info query supported filter
var RESOURCE_DISTRIBUTION_SUPPORT_FILTERS = []string{
"res_name",
"is_dynamic",
"location",
}
var RESOURCE_DEFINITION_SUPPORT_FILTERS = []string{
"res_name",
}
type ResourceDistributionInfo struct {
ResourceName string `json:"res_name"`
IsDynamic bool `json:"is_dynamic"`
ValueType int `json:"value_type"`
BooleanValue bool `json:"boolean_value"`
StringValue string `json:"string_value"`
NumericValue float64 `json:"numeric_value"`
Location string `json:"location"`
}
type ResourceDefinitionInfo struct {
ResourceName string `json:"res_name"`
Description string `json:"description"`
ValueType int `json:"value_type"`
OrderType int `json:"order_type"`
Flag int `json:"flag"`
Interval int `json:"interval"`
}
var RESOURCE_DISTRIBUTION_SUPPORT_SORT = []string{
"res_name",
}

View file

@ -0,0 +1,84 @@
package models
var RolesAvailableTypes = []string{"builtin", "all"}
var BUILTIN_ROLE_NAMES = []string{
"basic_user",
"cluster_admin",
"queue_admin",
}
var ROLE_SUPPORT_FILTERS = []string{
"role_name",
"action",
}
var ROLE_SUPPORT_SORT = []string{
"role_name",
"action",
}
var ROLE_DEFAULT_COLUMN = []string{
"role_name",
"action",
"domain_type",
"domain_values",
}
var JSONBRFields = []string{"domain_values"}
type RoleFields struct {
RoleName string `json:"role_name"`
}
type RoleInfo struct {
RoleName string `json:"role_name"`
Action string `json:"action"`
DomainType string `json:"domain_type"`
DomainValues Jsonb `json:"domain_values"`
}
type RolePermission struct {
Permission string `json:"permission_name" binding:"required"`
DomainType string `json:"domain_type" binding:"required"`
DomainValues []string `json:"domain_values"`
}
type CreateRoleRequest struct {
RoleName string `json:"role_name" binding:"required"`
RolePermissions []RolePermission `json:"permissions" binding:"required"`
}
const (
DomainTypeAll = "all"
DomainTypeSelf = "self"
DomainTypeCluster = "cluster"
DomainTypeJob = "job"
DomainTypeQueue = "queue"
DomainTypeHost = "host"
DomainTypeUser = "user"
DomainTypeFile = "file"
DomainTypeHostGroup = "hostgroup"
DomainTypeUserGroup = "usergroup"
DomainTypeResource = "resource"
DomainTypeSelfUG = "self_ug"
DomainTypeSelfHG = "self_hg"
DomainTypeRBAC = "rbac"
)
var SupportedDomainTypes = map[string][]string{
DomainTypeCluster: {DomainTypeAll},
DomainTypeJob: {DomainTypeAll, DomainTypeSelf, DomainTypeSelfUG},
DomainTypeQueue: {DomainTypeAll, DomainTypeQueue},
DomainTypeHost: {DomainTypeAll, DomainTypeHostGroup},
DomainTypeUser: {DomainTypeAll, DomainTypeSelf},
DomainTypeFile: {DomainTypeAll, DomainTypeSelf},
DomainTypeHostGroup: {DomainTypeAll, DomainTypeSelfHG, DomainTypeHostGroup},
DomainTypeUserGroup: {DomainTypeAll, DomainTypeSelfUG, DomainTypeUserGroup},
DomainTypeResource: {DomainTypeAll, DomainTypeSelf},
DomainTypeRBAC: {DomainTypeAll, DomainTypeSelf},
}
type RoleCreateResponse struct {
RoleName string `json:"role_name"`
Message string `json:"message"`
}

View file

@ -0,0 +1,33 @@
package models
var USER_SUPPORT_FILTERS = []string{
"user_name",
"role_name",
}
var USER_SUPPORT_SORT = []string{
"user_name",
"role_name",
}
var JSONBUFields = []string{"domain_values"}
type AddRoleForUserRequest struct {
UserName string `json:"user_name" binding:"required"`
RoleName []string `json:"role_name" binding:"required"`
}
type UserInfo struct {
UserName string `json:"user_name"`
RoleName string `json:"role_name"`
}
type AddRoleForUserResponse struct {
UserName string `json:"user_name"`
Message string `json:"message"`
}
var USER_DEFAULT_COLUMN = []string{
"user_name",
"role_name",
}