1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
14 "git.arvados.org/arvados.git/lib/dispatchcloud/scheduler"
15 "git.arvados.org/arvados.git/sdk/go/arvados"
16 "git.arvados.org/arvados.git/sdk/go/auth"
17 "git.arvados.org/arvados.git/sdk/go/httpserver"
20 // ContainerRequestCreate defers to railsProxy for everything except
21 // vocabulary checking.
22 func (conn *Conn) ContainerRequestCreate(ctx context.Context, opts arvados.CreateOptions) (arvados.ContainerRequest, error) {
24 err := conn.checkProperties(ctx, opts.Attrs["properties"])
26 return arvados.ContainerRequest{}, err
28 resp, err := conn.railsProxy.ContainerRequestCreate(ctx, opts)
35 // ContainerRequestUpdate defers to railsProxy for everything except
36 // vocabulary checking.
37 func (conn *Conn) ContainerRequestUpdate(ctx context.Context, opts arvados.UpdateOptions) (arvados.ContainerRequest, error) {
39 err := conn.checkProperties(ctx, opts.Attrs["properties"])
41 return arvados.ContainerRequest{}, err
43 resp, err := conn.railsProxy.ContainerRequestUpdate(ctx, opts)
50 func (conn *Conn) ContainerRequestGet(ctx context.Context, opts arvados.GetOptions) (arvados.ContainerRequest, error) {
52 return conn.railsProxy.ContainerRequestGet(ctx, opts)
55 func (conn *Conn) ContainerRequestList(ctx context.Context, opts arvados.ListOptions) (arvados.ContainerRequestList, error) {
57 return conn.railsProxy.ContainerRequestList(ctx, opts)
60 func (conn *Conn) ContainerRequestDelete(ctx context.Context, opts arvados.DeleteOptions) (arvados.ContainerRequest, error) {
62 return conn.railsProxy.ContainerRequestDelete(ctx, opts)
65 func (conn *Conn) ContainerRequestContainerStatus(ctx context.Context, opts arvados.GetOptions) (arvados.ContainerStatus, error) {
67 var ret arvados.ContainerStatus
68 cr, err := conn.railsProxy.ContainerRequestGet(ctx, arvados.GetOptions{UUID: opts.UUID, Select: []string{"uuid", "container_uuid", "log_uuid"}})
72 if cr.ContainerUUID == "" {
73 ret.SchedulingStatus = "no container assigned"
76 // We use admin credentials to get the container record so we
77 // don't get an error when we're in a race with auto-retry and
78 // the container became user-unreadable since we fetched the
80 ctxRoot := auth.NewContext(ctx, &auth.Credentials{Tokens: []string{conn.cluster.SystemRootToken}})
81 ctr, err := conn.railsProxy.ContainerGet(ctxRoot, arvados.GetOptions{UUID: cr.ContainerUUID, Select: []string{"uuid", "state", "priority"}})
87 if ctr.State != arvados.ContainerStateQueued && ctr.State != arvados.ContainerStateLocked {
88 // Scheduling status is not a thing once the container
89 // is in running state.
93 for dispatchurl := range conn.cluster.Services.DispatchCloud.InternalURLs {
94 baseurl := url.URL(dispatchurl)
95 apiurl, err := baseurl.Parse("/arvados/v1/dispatch/container?container_uuid=" + cr.ContainerUUID)
100 req, err := http.NewRequestWithContext(ctx, http.MethodGet, apiurl.String(), nil)
105 req.Header.Set("Authorization", "Bearer "+conn.cluster.ManagementToken)
106 resp, err := http.DefaultClient.Do(req)
108 lastErr = fmt.Errorf("error getting status from dispatcher: %w", err)
111 if resp.StatusCode == http.StatusNotFound {
113 } else if resp.StatusCode != http.StatusOK {
114 lastErr = fmt.Errorf("error getting status from dispatcher: %s", resp.Status)
117 var qent scheduler.QueueEnt
118 err = json.NewDecoder(resp.Body).Decode(&qent)
123 ret.State = qent.Container.State // Prefer dispatcher's view of state if not equal to ctr.State
124 ret.SchedulingStatus = qent.SchedulingStatus
128 // If we got a non-nil error from a dispatchcloud
129 // service, and the container state suggests
130 // dispatchcloud should know about it, then we return
131 // an error so the client knows to retry.
132 return ret, httpserver.ErrorWithStatus(lastErr, http.StatusBadGateway)
134 // All running dispatchcloud services confirm they don't have
135 // this container (the dispatcher hasn't yet noticed it
136 // appearing in the queue) or there are no dispatchcloud
137 // services configured. Either way, all we can say is that
139 if ctr.State == arvados.ContainerStateQueued && ctr.Priority < 1 {
140 // If it hasn't been picked up by a dispatcher
141 // already, it won't be -- it's just on hold.
142 // Scheduling status does not apply.
145 ret.SchedulingStatus = "waiting for dispatch"