Beispiel #1
0
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)
}
Beispiel #2
0
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
}
Beispiel #3
0
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
}
Beispiel #4
0
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)
}
Beispiel #5
0
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}
}