func operationGet(d *Daemon, r *http.Request) Response { id := shared.OperationsURL(mux.Vars(r)["id"]) operationLock.Lock() defer operationLock.Unlock() op, ok := operations[id] if !ok { return NotFound } return SyncResponse(true, op) }
func createOperation(metadata shared.Jmap, resources map[string][]string, run func(id string) shared.OperationResult, cancel func(id string) error, ws shared.OperationWebsocket) (string, error) { id := uuid.NewV4().String() op := shared.Operation{} op.Id = id op.CreatedAt = time.Now() op.UpdatedAt = op.CreatedAt op.SetStatus(shared.Pending) if resources != nil { tmpResources := make(map[string][]string) for key, value := range resources { var values []string for _, c := range value { values = append(values, fmt.Sprintf("/%s/%s/%s", shared.APIVersion, key, c)) } tmpResources[key] = values } op.Resources = tmpResources } md, err := json.Marshal(metadata) if err != nil { return "", err } op.Metadata = md op.MayCancel = ((run == nil && cancel == nil) || cancel != nil) op.Run = run op.Cancel = cancel op.Chan = make(chan bool, 1) op.Websocket = ws url := shared.OperationsURL(id) operationLock.Lock() operations[url] = &op operationLock.Unlock() eventSend("operation", op) return url, nil }
func operationDelete(d *Daemon, r *http.Request) Response { operationLock.Lock() id := shared.OperationsURL(mux.Vars(r)["id"]) op, ok := operations[id] if !ok { operationLock.Unlock() return NotFound } if op.Cancel == nil && op.Run != nil { operationLock.Unlock() return BadRequest(fmt.Errorf("Can't cancel %s!", id)) } if op.StatusCode == shared.Cancelling || op.StatusCode.IsFinal() { /* the user has already requested a cancel, or the status is * in a final state. */ operationLock.Unlock() return EmptySyncResponse } if op.Cancel != nil { cancel := op.Cancel op.SetStatus(shared.Cancelling) operationLock.Unlock() err := cancel(id) operationLock.Lock() op.SetStatusByErr(err) operationLock.Unlock() if err != nil { return InternalError(err) } } else { op.SetStatus(shared.Cancelled) operationLock.Unlock() } return EmptySyncResponse }
func operationWaitGet(d *Daemon, r *http.Request) Response { targetStatus, err := shared.AtoiEmptyDefault(r.FormValue("status_code"), int(shared.Success)) if err != nil { return InternalError(err) } timeout, err := shared.AtoiEmptyDefault(r.FormValue("timeout"), -1) if err != nil { return InternalError(err) } operationLock.Lock() id := shared.OperationsURL(mux.Vars(r)["id"]) op, ok := operations[id] if !ok { operationLock.Unlock() return NotFound } status := op.StatusCode operationLock.Unlock() if int(status) != targetStatus && (status == shared.Pending || status == shared.Running) { if timeout >= 0 { select { case <-op.Chan: break case <-time.After(time.Duration(timeout) * time.Second): break } } else { <-op.Chan } } operationLock.Lock() defer operationLock.Unlock() return SyncResponse(true, op) }
func operationWebsocketGet(d *Daemon, r *http.Request) Response { operationLock.Lock() defer operationLock.Unlock() id := shared.OperationsURL(mux.Vars(r)["id"]) op, ok := operations[id] if !ok { return NotFound } if op.Websocket == nil { return BadRequest(fmt.Errorf("operation has no websocket protocol")) } secret := r.FormValue("secret") if secret == "" { return BadRequest(fmt.Errorf("missing secret")) } if op.StatusCode.IsFinal() { return BadRequest(fmt.Errorf("status is %s, can't connect", op.Status)) } return &websocketServe{r, secret, op} }