mirror of
				https://github.com/ClusterCockpit/cc-backend
				synced 2025-11-04 01:25:06 +01:00 
			
		
		
		
	@@ -327,6 +327,76 @@
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "/jobs/edit_meta/{id}": {
 | 
			
		||||
            "post": {
 | 
			
		||||
                "security": [
 | 
			
		||||
                    {
 | 
			
		||||
                        "ApiKeyAuth": []
 | 
			
		||||
                    }
 | 
			
		||||
                ],
 | 
			
		||||
                "description": "Edit key value pairs in job metadata json\nIf a key already exists its content will be overwritten",
 | 
			
		||||
                "consumes": [
 | 
			
		||||
                    "application/json"
 | 
			
		||||
                ],
 | 
			
		||||
                "produces": [
 | 
			
		||||
                    "application/json"
 | 
			
		||||
                ],
 | 
			
		||||
                "tags": [
 | 
			
		||||
                    "Job add and modify"
 | 
			
		||||
                ],
 | 
			
		||||
                "summary": "Edit meta-data json",
 | 
			
		||||
                "parameters": [
 | 
			
		||||
                    {
 | 
			
		||||
                        "type": "integer",
 | 
			
		||||
                        "description": "Job Database ID",
 | 
			
		||||
                        "name": "id",
 | 
			
		||||
                        "in": "path",
 | 
			
		||||
                        "required": true
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        "description": "Kay value pair to add",
 | 
			
		||||
                        "name": "request",
 | 
			
		||||
                        "in": "body",
 | 
			
		||||
                        "required": true,
 | 
			
		||||
                        "schema": {
 | 
			
		||||
                            "$ref": "#/definitions/api.EditMetaRequest"
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                ],
 | 
			
		||||
                "responses": {
 | 
			
		||||
                    "200": {
 | 
			
		||||
                        "description": "Updated job resource",
 | 
			
		||||
                        "schema": {
 | 
			
		||||
                            "$ref": "#/definitions/schema.Job"
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    "400": {
 | 
			
		||||
                        "description": "Bad Request",
 | 
			
		||||
                        "schema": {
 | 
			
		||||
                            "$ref": "#/definitions/api.ErrorResponse"
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    "401": {
 | 
			
		||||
                        "description": "Unauthorized",
 | 
			
		||||
                        "schema": {
 | 
			
		||||
                            "$ref": "#/definitions/api.ErrorResponse"
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    "404": {
 | 
			
		||||
                        "description": "Job does not exist",
 | 
			
		||||
                        "schema": {
 | 
			
		||||
                            "$ref": "#/definitions/api.ErrorResponse"
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    "500": {
 | 
			
		||||
                        "description": "Internal Server Error",
 | 
			
		||||
                        "schema": {
 | 
			
		||||
                            "$ref": "#/definitions/api.ErrorResponse"
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "/jobs/start_job/": {
 | 
			
		||||
            "post": {
 | 
			
		||||
                "security": [
 | 
			
		||||
@@ -1114,6 +1184,19 @@
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "api.EditMetaRequest": {
 | 
			
		||||
            "type": "object",
 | 
			
		||||
            "properties": {
 | 
			
		||||
                "key": {
 | 
			
		||||
                    "type": "string",
 | 
			
		||||
                    "example": "jobScript"
 | 
			
		||||
                },
 | 
			
		||||
                "value": {
 | 
			
		||||
                    "type": "string",
 | 
			
		||||
                    "example": "bash script"
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "api.ErrorResponse": {
 | 
			
		||||
            "type": "object",
 | 
			
		||||
            "properties": {
 | 
			
		||||
@@ -1252,6 +1335,10 @@
 | 
			
		||||
                    "minimum": 0,
 | 
			
		||||
                    "example": 1
 | 
			
		||||
                },
 | 
			
		||||
                "flopsAnyAvg": {
 | 
			
		||||
                    "description": "FlopsAnyAvg as Float64",
 | 
			
		||||
                    "type": "number"
 | 
			
		||||
                },
 | 
			
		||||
                "id": {
 | 
			
		||||
                    "description": "The unique identifier of a job in the database",
 | 
			
		||||
                    "type": "integer"
 | 
			
		||||
@@ -1278,6 +1365,18 @@
 | 
			
		||||
                    ],
 | 
			
		||||
                    "example": "completed"
 | 
			
		||||
                },
 | 
			
		||||
                "loadAvg": {
 | 
			
		||||
                    "description": "LoadAvg as Float64",
 | 
			
		||||
                    "type": "number"
 | 
			
		||||
                },
 | 
			
		||||
                "memBwAvg": {
 | 
			
		||||
                    "description": "MemBwAvg as Float64",
 | 
			
		||||
                    "type": "number"
 | 
			
		||||
                },
 | 
			
		||||
                "memUsedMax": {
 | 
			
		||||
                    "description": "MemUsedMax as Float64",
 | 
			
		||||
                    "type": "number"
 | 
			
		||||
                },
 | 
			
		||||
                "metaData": {
 | 
			
		||||
                    "description": "Additional information about the job",
 | 
			
		||||
                    "type": "object",
 | 
			
		||||
 
 | 
			
		||||
@@ -50,6 +50,15 @@ definitions:
 | 
			
		||||
      msg:
 | 
			
		||||
        type: string
 | 
			
		||||
    type: object
 | 
			
		||||
  api.EditMetaRequest:
 | 
			
		||||
    properties:
 | 
			
		||||
      key:
 | 
			
		||||
        example: jobScript
 | 
			
		||||
        type: string
 | 
			
		||||
      value:
 | 
			
		||||
        example: bash script
 | 
			
		||||
        type: string
 | 
			
		||||
    type: object
 | 
			
		||||
  api.ErrorResponse:
 | 
			
		||||
    properties:
 | 
			
		||||
      error:
 | 
			
		||||
@@ -150,6 +159,9 @@ definitions:
 | 
			
		||||
        maximum: 2
 | 
			
		||||
        minimum: 0
 | 
			
		||||
        type: integer
 | 
			
		||||
      flopsAnyAvg:
 | 
			
		||||
        description: FlopsAnyAvg as Float64
 | 
			
		||||
        type: number
 | 
			
		||||
      id:
 | 
			
		||||
        description: The unique identifier of a job in the database
 | 
			
		||||
        type: integer
 | 
			
		||||
@@ -169,6 +181,15 @@ definitions:
 | 
			
		||||
        - timeout
 | 
			
		||||
        - out_of_memory
 | 
			
		||||
        example: completed
 | 
			
		||||
      loadAvg:
 | 
			
		||||
        description: LoadAvg as Float64
 | 
			
		||||
        type: number
 | 
			
		||||
      memBwAvg:
 | 
			
		||||
        description: MemBwAvg as Float64
 | 
			
		||||
        type: number
 | 
			
		||||
      memUsedMax:
 | 
			
		||||
        description: MemUsedMax as Float64
 | 
			
		||||
        type: number
 | 
			
		||||
      metaData:
 | 
			
		||||
        additionalProperties:
 | 
			
		||||
          type: string
 | 
			
		||||
@@ -810,6 +831,53 @@ paths:
 | 
			
		||||
      summary: Remove a job from the sql database
 | 
			
		||||
      tags:
 | 
			
		||||
      - Job remove
 | 
			
		||||
  /jobs/edit_meta/{id}:
 | 
			
		||||
    post:
 | 
			
		||||
      consumes:
 | 
			
		||||
      - application/json
 | 
			
		||||
      description: |-
 | 
			
		||||
        Edit key value pairs in job metadata json
 | 
			
		||||
        If a key already exists its content will be overwritten
 | 
			
		||||
      parameters:
 | 
			
		||||
      - description: Job Database ID
 | 
			
		||||
        in: path
 | 
			
		||||
        name: id
 | 
			
		||||
        required: true
 | 
			
		||||
        type: integer
 | 
			
		||||
      - description: Kay value pair to add
 | 
			
		||||
        in: body
 | 
			
		||||
        name: request
 | 
			
		||||
        required: true
 | 
			
		||||
        schema:
 | 
			
		||||
          $ref: '#/definitions/api.EditMetaRequest'
 | 
			
		||||
      produces:
 | 
			
		||||
      - application/json
 | 
			
		||||
      responses:
 | 
			
		||||
        "200":
 | 
			
		||||
          description: Updated job resource
 | 
			
		||||
          schema:
 | 
			
		||||
            $ref: '#/definitions/schema.Job'
 | 
			
		||||
        "400":
 | 
			
		||||
          description: Bad Request
 | 
			
		||||
          schema:
 | 
			
		||||
            $ref: '#/definitions/api.ErrorResponse'
 | 
			
		||||
        "401":
 | 
			
		||||
          description: Unauthorized
 | 
			
		||||
          schema:
 | 
			
		||||
            $ref: '#/definitions/api.ErrorResponse'
 | 
			
		||||
        "404":
 | 
			
		||||
          description: Job does not exist
 | 
			
		||||
          schema:
 | 
			
		||||
            $ref: '#/definitions/api.ErrorResponse'
 | 
			
		||||
        "500":
 | 
			
		||||
          description: Internal Server Error
 | 
			
		||||
          schema:
 | 
			
		||||
            $ref: '#/definitions/api.ErrorResponse'
 | 
			
		||||
      security:
 | 
			
		||||
      - ApiKeyAuth: []
 | 
			
		||||
      summary: Edit meta-data json
 | 
			
		||||
      tags:
 | 
			
		||||
      - Job add and modify
 | 
			
		||||
  /jobs/start_job/:
 | 
			
		||||
    post:
 | 
			
		||||
      consumes:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
// Code generated by swaggo/swag. DO NOT EDIT.
 | 
			
		||||
 | 
			
		||||
// Package api Code generated by swaggo/swag. DO NOT EDIT
 | 
			
		||||
package api
 | 
			
		||||
 | 
			
		||||
import "github.com/swaggo/swag"
 | 
			
		||||
@@ -334,6 +333,76 @@ const docTemplate = `{
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "/jobs/edit_meta/{id}": {
 | 
			
		||||
            "post": {
 | 
			
		||||
                "security": [
 | 
			
		||||
                    {
 | 
			
		||||
                        "ApiKeyAuth": []
 | 
			
		||||
                    }
 | 
			
		||||
                ],
 | 
			
		||||
                "description": "Edit key value pairs in job metadata json\nIf a key already exists its content will be overwritten",
 | 
			
		||||
                "consumes": [
 | 
			
		||||
                    "application/json"
 | 
			
		||||
                ],
 | 
			
		||||
                "produces": [
 | 
			
		||||
                    "application/json"
 | 
			
		||||
                ],
 | 
			
		||||
                "tags": [
 | 
			
		||||
                    "Job add and modify"
 | 
			
		||||
                ],
 | 
			
		||||
                "summary": "Edit meta-data json",
 | 
			
		||||
                "parameters": [
 | 
			
		||||
                    {
 | 
			
		||||
                        "type": "integer",
 | 
			
		||||
                        "description": "Job Database ID",
 | 
			
		||||
                        "name": "id",
 | 
			
		||||
                        "in": "path",
 | 
			
		||||
                        "required": true
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        "description": "Kay value pair to add",
 | 
			
		||||
                        "name": "request",
 | 
			
		||||
                        "in": "body",
 | 
			
		||||
                        "required": true,
 | 
			
		||||
                        "schema": {
 | 
			
		||||
                            "$ref": "#/definitions/api.EditMetaRequest"
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                ],
 | 
			
		||||
                "responses": {
 | 
			
		||||
                    "200": {
 | 
			
		||||
                        "description": "Updated job resource",
 | 
			
		||||
                        "schema": {
 | 
			
		||||
                            "$ref": "#/definitions/schema.Job"
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    "400": {
 | 
			
		||||
                        "description": "Bad Request",
 | 
			
		||||
                        "schema": {
 | 
			
		||||
                            "$ref": "#/definitions/api.ErrorResponse"
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    "401": {
 | 
			
		||||
                        "description": "Unauthorized",
 | 
			
		||||
                        "schema": {
 | 
			
		||||
                            "$ref": "#/definitions/api.ErrorResponse"
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    "404": {
 | 
			
		||||
                        "description": "Job does not exist",
 | 
			
		||||
                        "schema": {
 | 
			
		||||
                            "$ref": "#/definitions/api.ErrorResponse"
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    "500": {
 | 
			
		||||
                        "description": "Internal Server Error",
 | 
			
		||||
                        "schema": {
 | 
			
		||||
                            "$ref": "#/definitions/api.ErrorResponse"
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "/jobs/start_job/": {
 | 
			
		||||
            "post": {
 | 
			
		||||
                "security": [
 | 
			
		||||
@@ -1121,6 +1190,19 @@ const docTemplate = `{
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "api.EditMetaRequest": {
 | 
			
		||||
            "type": "object",
 | 
			
		||||
            "properties": {
 | 
			
		||||
                "key": {
 | 
			
		||||
                    "type": "string",
 | 
			
		||||
                    "example": "jobScript"
 | 
			
		||||
                },
 | 
			
		||||
                "value": {
 | 
			
		||||
                    "type": "string",
 | 
			
		||||
                    "example": "bash script"
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "api.ErrorResponse": {
 | 
			
		||||
            "type": "object",
 | 
			
		||||
            "properties": {
 | 
			
		||||
@@ -1259,6 +1341,10 @@ const docTemplate = `{
 | 
			
		||||
                    "minimum": 0,
 | 
			
		||||
                    "example": 1
 | 
			
		||||
                },
 | 
			
		||||
                "flopsAnyAvg": {
 | 
			
		||||
                    "description": "FlopsAnyAvg as Float64",
 | 
			
		||||
                    "type": "number"
 | 
			
		||||
                },
 | 
			
		||||
                "id": {
 | 
			
		||||
                    "description": "The unique identifier of a job in the database",
 | 
			
		||||
                    "type": "integer"
 | 
			
		||||
@@ -1285,6 +1371,18 @@ const docTemplate = `{
 | 
			
		||||
                    ],
 | 
			
		||||
                    "example": "completed"
 | 
			
		||||
                },
 | 
			
		||||
                "loadAvg": {
 | 
			
		||||
                    "description": "LoadAvg as Float64",
 | 
			
		||||
                    "type": "number"
 | 
			
		||||
                },
 | 
			
		||||
                "memBwAvg": {
 | 
			
		||||
                    "description": "MemBwAvg as Float64",
 | 
			
		||||
                    "type": "number"
 | 
			
		||||
                },
 | 
			
		||||
                "memUsedMax": {
 | 
			
		||||
                    "description": "MemUsedMax as Float64",
 | 
			
		||||
                    "type": "number"
 | 
			
		||||
                },
 | 
			
		||||
                "metaData": {
 | 
			
		||||
                    "description": "Additional information about the job",
 | 
			
		||||
                    "type": "object",
 | 
			
		||||
 
 | 
			
		||||
@@ -71,6 +71,7 @@ func (api *RestApi) MountRoutes(r *mux.Router) {
 | 
			
		||||
	r.HandleFunc("/jobs/", api.getJobs).Methods(http.MethodGet)
 | 
			
		||||
	r.HandleFunc("/jobs/{id}", api.getJobById).Methods(http.MethodPost)
 | 
			
		||||
	r.HandleFunc("/jobs/tag_job/{id}", api.tagJob).Methods(http.MethodPost, http.MethodPatch)
 | 
			
		||||
	r.HandleFunc("/jobs/edit_meta/{id}", api.editMeta).Methods(http.MethodPost, http.MethodPatch)
 | 
			
		||||
	r.HandleFunc("/jobs/metrics/{id}", api.getJobMetrics).Methods(http.MethodGet)
 | 
			
		||||
	r.HandleFunc("/jobs/delete_job/", api.deleteJobByRequest).Methods(http.MethodDelete)
 | 
			
		||||
	r.HandleFunc("/jobs/delete_job/{id}", api.deleteJobById).Methods(http.MethodDelete)
 | 
			
		||||
@@ -146,6 +147,12 @@ type ApiTag struct {
 | 
			
		||||
	Name string `json:"name" example:"Testjob"` // Tag Name
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ApiMeta model
 | 
			
		||||
type EditMetaRequest struct {
 | 
			
		||||
	Key   string `json:"key" example:"jobScript"`
 | 
			
		||||
	Value string `json:"value" example:"bash script"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type TagJobApiRequest []*ApiTag
 | 
			
		||||
 | 
			
		||||
type GetJobApiRequest []string
 | 
			
		||||
@@ -243,7 +250,6 @@ func securedCheck(r *http.Request) error {
 | 
			
		||||
// @security    ApiKeyAuth
 | 
			
		||||
// @router      /jobs/ [get]
 | 
			
		||||
func (api *RestApi) getJobs(rw http.ResponseWriter, r *http.Request) {
 | 
			
		||||
 | 
			
		||||
	if user := repository.GetUserFromContext(r.Context()); user != nil &&
 | 
			
		||||
		!user.HasRole(schema.RoleApi) {
 | 
			
		||||
 | 
			
		||||
@@ -464,6 +470,57 @@ func (api *RestApi) getJobById(rw http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// editMeta godoc
 | 
			
		||||
// @summary    Edit meta-data json
 | 
			
		||||
// @tags Job add and modify
 | 
			
		||||
// @description Edit key value pairs in job metadata json
 | 
			
		||||
// @description If a key already exists its content will be overwritten
 | 
			
		||||
// @accept      json
 | 
			
		||||
// @produce     json
 | 
			
		||||
// @param       id      path     int                  true "Job Database ID"
 | 
			
		||||
// @param       request body     api.EditMetaRequest  true "Kay value pair to add"
 | 
			
		||||
// @success     200     {object} schema.Job                "Updated job resource"
 | 
			
		||||
// @failure     400     {object} api.ErrorResponse         "Bad Request"
 | 
			
		||||
// @failure     401     {object} api.ErrorResponse         "Unauthorized"
 | 
			
		||||
// @failure     404     {object} api.ErrorResponse         "Job does not exist"
 | 
			
		||||
// @failure     500     {object} api.ErrorResponse         "Internal Server Error"
 | 
			
		||||
// @security    ApiKeyAuth
 | 
			
		||||
// @router      /jobs/edit_meta/{id} [post]
 | 
			
		||||
func (api *RestApi) editMeta(rw http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	if user := repository.GetUserFromContext(r.Context()); user != nil &&
 | 
			
		||||
		!user.HasRole(schema.RoleApi) {
 | 
			
		||||
		handleError(fmt.Errorf("missing role: %v", schema.GetRoleString(schema.RoleApi)), http.StatusForbidden, rw)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	iid, err := strconv.ParseInt(mux.Vars(r)["id"], 10, 64)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		http.Error(rw, err.Error(), http.StatusBadRequest)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	job, err := api.JobRepository.FindById(iid)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		http.Error(rw, err.Error(), http.StatusNotFound)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var req EditMetaRequest
 | 
			
		||||
	if err := decode(r.Body, &req); err != nil {
 | 
			
		||||
		http.Error(rw, err.Error(), http.StatusBadRequest)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := api.JobRepository.UpdateMetadata(job, req.Key, req.Value); err != nil {
 | 
			
		||||
		http.Error(rw, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rw.Header().Add("Content-Type", "application/json")
 | 
			
		||||
	rw.WriteHeader(http.StatusOK)
 | 
			
		||||
	json.NewEncoder(rw).Encode(job)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// tagJob godoc
 | 
			
		||||
// @summary     Adds one or more tags to a job
 | 
			
		||||
// @tags Job add and modify
 | 
			
		||||
@@ -873,7 +930,6 @@ func (api *RestApi) deleteJobBefore(rw http.ResponseWriter, r *http.Request) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (api *RestApi) checkAndHandleStopJob(rw http.ResponseWriter, job *schema.Job, req StopJobApiRequest) {
 | 
			
		||||
 | 
			
		||||
	// Sanity checks
 | 
			
		||||
	if job == nil || job.StartTime.Unix() >= req.StopTime || job.State != schema.JobStateRunning {
 | 
			
		||||
		handleError(errors.New("stopTime must be larger than startTime and only running jobs can be stopped"), http.StatusBadRequest, rw)
 | 
			
		||||
@@ -1015,7 +1071,8 @@ func (api *RestApi) createUser(rw http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		Password: password,
 | 
			
		||||
		Email:    email,
 | 
			
		||||
		Projects: []string{project},
 | 
			
		||||
		Roles:    []string{role}}); err != nil {
 | 
			
		||||
		Roles:    []string{role},
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		http.Error(rw, err.Error(), http.StatusUnprocessableEntity)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	"github.com/ClusterCockpit/cc-backend/internal/graph/model"
 | 
			
		||||
	"github.com/ClusterCockpit/cc-backend/internal/metricdata"
 | 
			
		||||
	"github.com/ClusterCockpit/cc-backend/pkg/archive"
 | 
			
		||||
	"github.com/ClusterCockpit/cc-backend/pkg/log"
 | 
			
		||||
	"github.com/ClusterCockpit/cc-backend/pkg/lrucache"
 | 
			
		||||
	"github.com/ClusterCockpit/cc-backend/pkg/schema"
 | 
			
		||||
@@ -212,7 +213,7 @@ func (r *JobRepository) UpdateMetadata(job *schema.Job, key, val string) (err er
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r.cache.Put(cachekey, job.MetaData, len(job.RawMetaData), 24*time.Hour)
 | 
			
		||||
	return nil
 | 
			
		||||
	return archive.UpdateMetadata(job, job.MetaData)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Find executes a SQL query to find a specific batch job.
 | 
			
		||||
@@ -223,8 +224,8 @@ func (r *JobRepository) UpdateMetadata(job *schema.Job, key, val string) (err er
 | 
			
		||||
func (r *JobRepository) Find(
 | 
			
		||||
	jobId *int64,
 | 
			
		||||
	cluster *string,
 | 
			
		||||
	startTime *int64) (*schema.Job, error) {
 | 
			
		||||
 | 
			
		||||
	startTime *int64,
 | 
			
		||||
) (*schema.Job, error) {
 | 
			
		||||
	start := time.Now()
 | 
			
		||||
	q := sq.Select(jobColumns...).From("job").
 | 
			
		||||
		Where("job.job_id = ?", *jobId)
 | 
			
		||||
@@ -248,8 +249,8 @@ func (r *JobRepository) Find(
 | 
			
		||||
func (r *JobRepository) FindAll(
 | 
			
		||||
	jobId *int64,
 | 
			
		||||
	cluster *string,
 | 
			
		||||
	startTime *int64) ([]*schema.Job, error) {
 | 
			
		||||
 | 
			
		||||
	startTime *int64,
 | 
			
		||||
) ([]*schema.Job, error) {
 | 
			
		||||
	start := time.Now()
 | 
			
		||||
	q := sq.Select(jobColumns...).From("job").
 | 
			
		||||
		Where("job.job_id = ?", *jobId)
 | 
			
		||||
@@ -292,7 +293,8 @@ func (r *JobRepository) FindById(jobId int64) (*schema.Job, error) {
 | 
			
		||||
 | 
			
		||||
func (r *JobRepository) FindConcurrentJobs(
 | 
			
		||||
	ctx context.Context,
 | 
			
		||||
	job *schema.Job) (*model.JobLinkResultList, error) {
 | 
			
		||||
	job *schema.Job,
 | 
			
		||||
) (*model.JobLinkResultList, error) {
 | 
			
		||||
	if job == nil {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
@@ -420,8 +422,8 @@ func (r *JobRepository) Stop(
 | 
			
		||||
	jobId int64,
 | 
			
		||||
	duration int32,
 | 
			
		||||
	state schema.JobState,
 | 
			
		||||
	monitoringStatus int32) (err error) {
 | 
			
		||||
 | 
			
		||||
	monitoringStatus int32,
 | 
			
		||||
) (err error) {
 | 
			
		||||
	stmt := sq.Update("job").
 | 
			
		||||
		Set("job_state", state).
 | 
			
		||||
		Set("duration", duration).
 | 
			
		||||
@@ -435,7 +437,7 @@ func (r *JobRepository) Stop(
 | 
			
		||||
func (r *JobRepository) DeleteJobsBefore(startTime int64) (int, error) {
 | 
			
		||||
	var cnt int
 | 
			
		||||
	qs := fmt.Sprintf("SELECT count(*) FROM job WHERE job.start_time < %d", startTime)
 | 
			
		||||
	err := r.DB.Get(&cnt, qs) //ignore error as it will also occur in delete statement
 | 
			
		||||
	err := r.DB.Get(&cnt, qs) // ignore error as it will also occur in delete statement
 | 
			
		||||
	_, err = r.DB.Exec(`DELETE FROM job WHERE job.start_time < ?`, startTime)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Errorf(" DeleteJobsBefore(%d): error %#v", startTime, err)
 | 
			
		||||
@@ -468,8 +470,8 @@ func (r *JobRepository) UpdateMonitoringStatus(job int64, monitoringStatus int32
 | 
			
		||||
func (r *JobRepository) MarkArchived(
 | 
			
		||||
	jobId int64,
 | 
			
		||||
	monitoringStatus int32,
 | 
			
		||||
	metricStats map[string]schema.JobStatistics) error {
 | 
			
		||||
 | 
			
		||||
	metricStats map[string]schema.JobStatistics,
 | 
			
		||||
) error {
 | 
			
		||||
	stmt := sq.Update("job").
 | 
			
		||||
		Set("monitoring_status", monitoringStatus).
 | 
			
		||||
		Where("job.id = ?", jobId)
 | 
			
		||||
@@ -578,8 +580,10 @@ func (r *JobRepository) FindUserOrProjectOrJobname(user *schema.User, searchterm
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var ErrNotFound = errors.New("no such jobname, project or user")
 | 
			
		||||
var ErrForbidden = errors.New("not authorized")
 | 
			
		||||
var (
 | 
			
		||||
	ErrNotFound  = errors.New("no such jobname, project or user")
 | 
			
		||||
	ErrForbidden = errors.New("not authorized")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (r *JobRepository) FindColumnValue(user *schema.User, searchterm string, table string, selectColumn string, whereColumn string, isLike bool) (result string, err error) {
 | 
			
		||||
	compareStr := " = ?"
 | 
			
		||||
@@ -663,7 +667,6 @@ func (r *JobRepository) Partitions(cluster string) ([]string, error) {
 | 
			
		||||
// AllocatedNodes returns a map of all subclusters to a map of hostnames to the amount of jobs running on that host.
 | 
			
		||||
// Hosts with zero jobs running on them will not show up!
 | 
			
		||||
func (r *JobRepository) AllocatedNodes(cluster string) (map[string]map[string]int, error) {
 | 
			
		||||
 | 
			
		||||
	start := time.Now()
 | 
			
		||||
	subclusters := make(map[string]map[string]int)
 | 
			
		||||
	rows, err := sq.Select("resources", "subcluster").From("job").
 | 
			
		||||
@@ -706,7 +709,6 @@ func (r *JobRepository) AllocatedNodes(cluster string) (map[string]map[string]in
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *JobRepository) StopJobsExceedingWalltimeBy(seconds int) error {
 | 
			
		||||
 | 
			
		||||
	start := time.Now()
 | 
			
		||||
	res, err := sq.Update("job").
 | 
			
		||||
		Set("monitoring_status", schema.MonitoringStatusArchivingFailed).
 | 
			
		||||
@@ -735,7 +737,6 @@ func (r *JobRepository) StopJobsExceedingWalltimeBy(seconds int) error {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *JobRepository) FindJobsBetween(startTimeBegin int64, startTimeEnd int64) ([]*schema.Job, error) {
 | 
			
		||||
 | 
			
		||||
	var query sq.SelectBuilder
 | 
			
		||||
 | 
			
		||||
	if startTimeBegin == startTimeEnd || startTimeBegin > startTimeEnd {
 | 
			
		||||
 
 | 
			
		||||
@@ -52,9 +52,11 @@ type JobContainer struct {
 | 
			
		||||
	Data *schema.JobData
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var cache *lrucache.Cache = lrucache.New(128 * 1024 * 1024)
 | 
			
		||||
var ar ArchiveBackend
 | 
			
		||||
var useArchive bool
 | 
			
		||||
var (
 | 
			
		||||
	cache      *lrucache.Cache = lrucache.New(128 * 1024 * 1024)
 | 
			
		||||
	ar         ArchiveBackend
 | 
			
		||||
	useArchive bool
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func Init(rawConfig json.RawMessage, disableArchive bool) error {
 | 
			
		||||
	useArchive = !disableArchive
 | 
			
		||||
@@ -95,8 +97,8 @@ func GetHandle() ArchiveBackend {
 | 
			
		||||
func LoadAveragesFromArchive(
 | 
			
		||||
	job *schema.Job,
 | 
			
		||||
	metrics []string,
 | 
			
		||||
	data [][]schema.Float) error {
 | 
			
		||||
 | 
			
		||||
	data [][]schema.Float,
 | 
			
		||||
) error {
 | 
			
		||||
	metaFile, err := ar.LoadJobMeta(job)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Warn("Error while loading job metadata from archiveBackend")
 | 
			
		||||
@@ -115,7 +117,6 @@ func LoadAveragesFromArchive(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetStatistics(job *schema.Job) (map[string]schema.JobStatistics, error) {
 | 
			
		||||
 | 
			
		||||
	metaFile, err := ar.LoadJobMeta(job)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Warn("Error while loading job metadata from archiveBackend")
 | 
			
		||||
@@ -125,10 +126,29 @@ func GetStatistics(job *schema.Job) (map[string]schema.JobStatistics, error) {
 | 
			
		||||
	return metaFile.Statistics, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// If the job is archived, find its `meta.json` file and override the Metadata
 | 
			
		||||
// in that JSON file. If the job is not archived, nothing is done.
 | 
			
		||||
func UpdateMetadata(job *schema.Job, metadata map[string]string) error {
 | 
			
		||||
	if job.State == schema.JobStateRunning || !useArchive {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	jobMeta, err := ar.LoadJobMeta(job)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Warn("Error while loading job metadata from archiveBackend")
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for k, v := range metadata {
 | 
			
		||||
		jobMeta.MetaData[k] = v
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ar.StoreJobMeta(jobMeta)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// If the job is archived, find its `meta.json` file and override the tags list
 | 
			
		||||
// in that JSON file. If the job is not archived, nothing is done.
 | 
			
		||||
func UpdateTags(job *schema.Job, tags []*schema.Tag) error {
 | 
			
		||||
 | 
			
		||||
	if job.State == schema.JobStateRunning || !useArchive {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user