[arvados] updated: 2.7.1-39-g6672bb30c6
git repository hosting
git at public.arvados.org
Mon Apr 1 12:56:44 UTC 2024
Summary of changes:
build/run-tests.sh | 2 +-
doc/admin/upgrading.html.textile.liquid | 6 ++
.../install-dispatch.html.textile.liquid | 11 ++-
lib/config/config.default.yml | 27 +++++++-
lib/controller/integration_test.go | 81 ++++++++++++++++++----
lib/lsf/dispatch.go | 21 +++++-
lib/lsf/dispatch_test.go | 42 +++++++++--
sdk/go/arvados/config.go | 8 ++-
.../api/app/models/api_client_authorization.rb | 4 ++
services/api/app/models/container_request.rb | 5 +-
services/api/test/integration/remote_user_test.rb | 34 ++++++++-
11 files changed, 206 insertions(+), 35 deletions(-)
via 6672bb30c62b840a18e1f83812ec65a098c19109 (commit)
via cd97f79249a180b6952587a58fd524ed21bee05a (commit)
via d308b870d530b37c5e1f5ce4c79a2031c10963fc (commit)
from 7e82101003b5cb4055a8c1e870414f629e3955e6 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
commit 6672bb30c62b840a18e1f83812ec65a098c19109
Author: Tom Clegg <tom at curii.com>
Date: Fri Mar 29 16:39:09 2024 -0400
Merge branch '21617-fed-content'
fixes #21617
fixes #21533
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom at curii.com>
diff --git a/lib/controller/integration_test.go b/lib/controller/integration_test.go
index 4bf7a03447..a76e707c8d 100644
--- a/lib/controller/integration_test.go
+++ b/lib/controller/integration_test.go
@@ -28,6 +28,7 @@ import (
"git.arvados.org/arvados.git/sdk/go/arvadostest"
"git.arvados.org/arvados.git/sdk/go/ctxlog"
"git.arvados.org/arvados.git/sdk/go/httpserver"
+ "git.arvados.org/arvados.git/sdk/go/keepclient"
check "gopkg.in/check.v1"
)
@@ -167,6 +168,20 @@ func (s *IntegrationSuite) TestDefaultStorageClassesOnCollections(c *check.C) {
c.Assert(coll.StorageClassesDesired, check.DeepEquals, kc.DefaultStorageClasses)
}
+func (s *IntegrationSuite) createTestCollectionManifest(c *check.C, ac *arvados.Client, kc *keepclient.KeepClient, content string) string {
+ fs, err := (&arvados.Collection{}).FileSystem(ac, kc)
+ c.Assert(err, check.IsNil)
+ f, err := fs.OpenFile("test.txt", os.O_CREATE|os.O_RDWR, 0777)
+ c.Assert(err, check.IsNil)
+ _, err = io.WriteString(f, content)
+ c.Assert(err, check.IsNil)
+ err = f.Close()
+ c.Assert(err, check.IsNil)
+ mtxt, err := fs.MarshalManifest(".")
+ c.Assert(err, check.IsNil)
+ return mtxt
+}
+
func (s *IntegrationSuite) TestGetCollectionByPDH(c *check.C) {
conn1 := s.super.Conn("z1111")
rootctx1, _, _ := s.super.RootClients("z1111")
@@ -175,34 +190,70 @@ func (s *IntegrationSuite) TestGetCollectionByPDH(c *check.C) {
// Create the collection to find its PDH (but don't save it
// anywhere yet)
- var coll1 arvados.Collection
- fs1, err := coll1.FileSystem(ac1, kc1)
- c.Assert(err, check.IsNil)
- f, err := fs1.OpenFile("test.txt", os.O_CREATE|os.O_RDWR, 0777)
- c.Assert(err, check.IsNil)
- _, err = io.WriteString(f, "IntegrationSuite.TestGetCollectionByPDH")
- c.Assert(err, check.IsNil)
- err = f.Close()
- c.Assert(err, check.IsNil)
- mtxt, err := fs1.MarshalManifest(".")
- c.Assert(err, check.IsNil)
+ mtxt := s.createTestCollectionManifest(c, ac1, kc1, c.TestName())
pdh := arvados.PortableDataHash(mtxt)
// Looking up the PDH before saving returns 404 if cycle
// detection is working.
- _, err = conn1.CollectionGet(userctx1, arvados.GetOptions{UUID: pdh})
+ _, err := conn1.CollectionGet(userctx1, arvados.GetOptions{UUID: pdh})
c.Assert(err, check.ErrorMatches, `.*404 Not Found.*`)
// Save the collection on cluster z1111.
- coll1, err = conn1.CollectionCreate(userctx1, arvados.CreateOptions{Attrs: map[string]interface{}{
+ _, err = conn1.CollectionCreate(userctx1, arvados.CreateOptions{Attrs: map[string]interface{}{
"manifest_text": mtxt,
}})
c.Assert(err, check.IsNil)
// Retrieve the collection from cluster z3333.
- coll, err := conn3.CollectionGet(userctx1, arvados.GetOptions{UUID: pdh})
+ coll2, err := conn3.CollectionGet(userctx1, arvados.GetOptions{UUID: pdh})
c.Check(err, check.IsNil)
- c.Check(coll.PortableDataHash, check.Equals, pdh)
+ c.Check(coll2.PortableDataHash, check.Equals, pdh)
+}
+
+func (s *IntegrationSuite) TestFederation_Write1Read2(c *check.C) {
+ s.testFederationCollectionAccess(c, "z1111", "z2222")
+}
+
+func (s *IntegrationSuite) TestFederation_Write2Read1(c *check.C) {
+ s.testFederationCollectionAccess(c, "z2222", "z1111")
+}
+
+func (s *IntegrationSuite) TestFederation_Write2Read3(c *check.C) {
+ s.testFederationCollectionAccess(c, "z2222", "z3333")
+}
+
+func (s *IntegrationSuite) testFederationCollectionAccess(c *check.C, writeCluster, readCluster string) {
+ conn1 := s.super.Conn("z1111")
+ rootctx1, _, _ := s.super.RootClients("z1111")
+ _, ac1, _, _ := s.super.UserClients("z1111", rootctx1, c, conn1, s.oidcprovider.AuthEmail, true)
+
+ connW := s.super.Conn(writeCluster)
+ userctxW, acW, kcW := s.super.ClientsWithToken(writeCluster, ac1.AuthToken)
+ kcW.DiskCacheSize = keepclient.DiskCacheDisabled
+ connR := s.super.Conn(readCluster)
+ userctxR, acR, kcR := s.super.ClientsWithToken(readCluster, ac1.AuthToken)
+ kcR.DiskCacheSize = keepclient.DiskCacheDisabled
+
+ filedata := fmt.Sprintf("%s: write to %s, read from %s", c.TestName(), writeCluster, readCluster)
+ mtxt := s.createTestCollectionManifest(c, acW, kcW, filedata)
+ collW, err := connW.CollectionCreate(userctxW, arvados.CreateOptions{Attrs: map[string]interface{}{
+ "manifest_text": mtxt,
+ }})
+ c.Assert(err, check.IsNil)
+
+ collR, err := connR.CollectionGet(userctxR, arvados.GetOptions{UUID: collW.UUID})
+ if !c.Check(err, check.IsNil) {
+ return
+ }
+ fsR, err := collR.FileSystem(acR, kcR)
+ if !c.Check(err, check.IsNil) {
+ return
+ }
+ buf, err := fs.ReadFile(arvados.FS(fsR), "test.txt")
+ if !c.Check(err, check.IsNil) {
+ return
+ }
+ c.Check(string(buf), check.Equals, filedata)
}
// Tests bug #18004
diff --git a/services/api/app/models/api_client_authorization.rb b/services/api/app/models/api_client_authorization.rb
index a03ce4f899..8aeaf2f9cb 100644
--- a/services/api/app/models/api_client_authorization.rb
+++ b/services/api/app/models/api_client_authorization.rb
@@ -294,6 +294,10 @@ class ApiClientAuthorization < ArvadosModel
raise "remote cluster #{upstream_cluster_id} returned invalid token uuid #{token_uuid.inspect}"
end
rescue HTTPClient::BadResponseError => e
+ if e.res.status_code >= 400 && e.res.status_code < 500
+ # Remote cluster does not accept this token.
+ return nil
+ end
# CurrentApiToken#call and ApplicationController#render_error will
# propagate the status code from the #http_status method, so define
# that here.
diff --git a/services/api/test/integration/remote_user_test.rb b/services/api/test/integration/remote_user_test.rb
index f42fda4150..1a67522f4d 100644
--- a/services/api/test/integration/remote_user_test.rb
+++ b/services/api/test/integration/remote_user_test.rb
@@ -593,15 +593,43 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
assert_equal 'zzzzz-tpzed-anonymouspublic', json_response['uuid']
end
- [401, 403, 422, 500, 502, 503].each do |status|
- test "propagate #{status} response from getting remote token" do
+ [400, 401, 403, 422, 500, 502, 503].each do |status|
+ test "handle #{status} response when checking remote-provided v2 token" do
@stub_token_status = status
get "/arvados/v1/users/#{@stub_content[:uuid]}",
params: {format: "json"},
headers: auth(remote: "zbbbb")
- assert_response status
+ assert_response(status < 500 ? 401 : status)
end
+ test "handle #{status} response when checking remote-provided v2 token at anonymously accessible endpoint" do
+ @stub_token_status = status
+ get "/arvados/v1/keep_services/accessible",
+ params: {format: "json"},
+ headers: auth(remote: "zbbbb")
+ assert_response(status < 500 ? :success : status)
+ end
+
+ test "handle #{status} response when checking token issued by login cluster" do
+ @stub_token_status = status
+ Rails.configuration.Login.LoginCluster = "zbbbb"
+ get "/arvados/v1/users/current",
+ params: {format: "json"},
+ headers: {'HTTP_AUTHORIZATION' => "Bearer badtoken"}
+ assert_response(status < 500 ? 401 : status)
+ end
+
+ test "handle #{status} response when checking token issued by login cluster at anonymously accessible endpoint" do
+ @stub_token_status = status
+ Rails.configuration.Login.LoginCluster = "zbbbb"
+ get "/arvados/v1/keep_services/accessible",
+ params: {format: "json"},
+ headers: {'HTTP_AUTHORIZATION' => "Bearer badtoken"}
+ assert_response(status < 500 ? :success : status)
+ end
+ end
+
+ [401, 403, 422, 500, 502, 503].each do |status|
test "propagate #{status} response from getting uncached user" do
@stub_status = status
get "/arvados/v1/users/#{@stub_content[:uuid]}",
commit cd97f79249a180b6952587a58fd524ed21bee05a
Author: Peter Amstutz <peter.amstutz at curii.com>
Date: Thu Mar 28 14:52:18 2024 -0400
Add upgrading note about MaxRunTimeOverhead and MaxRunTimeDefault
refs #21463
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>
diff --git a/doc/admin/upgrading.html.textile.liquid b/doc/admin/upgrading.html.textile.liquid
index fe15518253..9139739e71 100644
--- a/doc/admin/upgrading.html.textile.liquid
+++ b/doc/admin/upgrading.html.textile.liquid
@@ -36,6 +36,12 @@ h3. Check MaxGatewayTunnels config
If you use the LSF or Slurm dispatcher, ensure the new @API.MaxGatewayTunnels@ config entry is high enough to support the size of your cluster. See "LSF docs":{{site.baseurl}}/install/crunch2-lsf/install-dispatch.html#MaxGatewayTunnels or "Slurm docs":{{site.baseurl}}/install/crunch2-slurm/install-dispatch.html#MaxGatewayTunnels for details.
+h3. New LSF dispatcher config items MaxRunTimeOverhead and MaxRunTimeDefault
+
+Now supports configuration parameter @Containers.LSF.MaxRunTimeDefault@ as the default value for @max_run_time@ for containers that do not specify a time limit (using CWL @ToolTimeLimit@).
+
+Now supports configuration parameter @Containers.LSF.MaxRunTimeOverhead@ so that when @scheduling_constraints.max_run_time@ or @MaxRunTimeDefault@ are non-zero, this adds time to account for crunch-run startup/shutdown overhead.
+
h2(#2_7_1). v2.7.1 (2023-12-12)
"previous: Upgrading to 2.7.0":#v2_7_0
commit d308b870d530b37c5e1f5ce4c79a2031c10963fc
Author: Tom Clegg <tom at curii.com>
Date: Mon Mar 18 10:48:05 2024 -0400
Merge branch '21449-lsf-maxruntime'
closes #21449
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom at curii.com>
diff --git a/build/run-tests.sh b/build/run-tests.sh
index 28051318b2..3aa1d65a3d 100755
--- a/build/run-tests.sh
+++ b/build/run-tests.sh
@@ -1070,9 +1070,9 @@ install_deps() {
# Install parts needed by test suites
do_install env
do_install cmd/arvados-server go
- do_install sdk/cli
do_install sdk/python pip "${VENV3DIR}/bin/"
do_install sdk/ruby
+ do_install sdk/cli
do_install services/api
do_install services/keepproxy go
do_install services/keep-web go
diff --git a/doc/install/crunch2-lsf/install-dispatch.html.textile.liquid b/doc/install/crunch2-lsf/install-dispatch.html.textile.liquid
index fc4393d0b6..6aeb11040c 100644
--- a/doc/install/crunch2-lsf/install-dispatch.html.textile.liquid
+++ b/doc/install/crunch2-lsf/install-dispatch.html.textile.liquid
@@ -75,6 +75,7 @@ Template variables starting with % will be substituted as follows:
%M memory in MB
%T tmp in MB
%G number of GPU devices (@runtime_constraints.cuda.device_count@)
+%W maximum job run time in minutes, suitable for use with @-W@ or @-We@ flags (see MaxRunTimeOverhead MaxRunTimeDefault below)
Use %% to express a literal %. The %%J in the default will be changed to %J, which is interpreted by @bsub@ itself.
@@ -83,7 +84,7 @@ For example:
<notextile>
<pre> Containers:
LSF:
- <code class="userinput">BsubArgumentsList: <b>["-o", "/tmp/crunch-run.%%J.out", "-e", "/tmp/crunch-run.%%J.err", "-J", "%U", "-n", "%C", "-D", "%MMB", "-R", "rusage[mem=%MMB:tmp=%TMB] span[hosts=1]", "-R", "select[mem>=%MMB]", "-R", "select[tmp>=%TMB]", "-R", "select[ncpus>=%C]"]</b></code>
+ <code class="userinput">BsubArgumentsList: <b>["-o", "/tmp/crunch-run.%%J.out", "-e", "/tmp/crunch-run.%%J.err", "-J", "%U", "-n", "%C", "-D", "%MMB", "-R", "rusage[mem=%MMB:tmp=%TMB] span[hosts=1]", "-R", "select[mem>=%MMB]", "-R", "select[tmp>=%TMB]", "-R", "select[ncpus>=%C]", "-We", "%W"]</b></code>
</pre>
</notextile>
@@ -100,6 +101,14 @@ If the container requests access to GPUs (@runtime_constraints.cuda.device_count
</pre>
</notextile>
+h3(#MaxRunTimeOverhead). Containers.LSF.MaxRunTimeOverhead
+
+Extra time to add to each container's @scheduling_parameters.max_run_time@ value when substituting for @%W@ in @BsubArgumentsList@, to account for time spent setting up the container image, copying output files, etc.
+
+h3(#MaxRunTimeDefault). Containers.LSF.MaxRunTimeDefault
+
+Default @max_run_time@ value to use for containers that do not specify one in @scheduling_parameters.max_run_time at . If this is zero, and @BsubArgumentsList@ contains @"-W", "%W"@ or @"-We", "%W"@, those arguments will be dropped when submitting containers that do not specify @scheduling_parameters.max_run_time at .
+
h3(#PollInterval). Containers.PollInterval
arvados-dispatch-lsf polls the API server periodically for new containers to run. The @PollInterval@ option controls how often this poll happens. Set this to a string of numbers suffixed with one of the time units @s@, @m@, or @h at . For example:
diff --git a/lib/config/config.default.yml b/lib/config/config.default.yml
index 8b434386ac..522a7ee4e0 100644
--- a/lib/config/config.default.yml
+++ b/lib/config/config.default.yml
@@ -1377,15 +1377,23 @@ Clusters:
# %M memory in MB
# %T tmp in MB
# %G number of GPU devices (runtime_constraints.cuda.device_count)
+ # %W maximum run time in minutes (see MaxRunTimeOverhead and
+ # MaxRunTimeDefault below)
#
- # Use %% to express a literal %. The %%J in the default will be changed
- # to %J, which is interpreted by bsub itself.
+ # Use %% to express a literal %. For example, the %%J in the
+ # default argument list will be changed to %J, which is
+ # interpreted by bsub itself.
#
# Note that the default arguments cause LSF to write two files
# in /tmp on the compute node each time an Arvados container
# runs. Ensure you have something in place to delete old files
# from /tmp, or adjust the "-o" and "-e" arguments accordingly.
- BsubArgumentsList: ["-o", "/tmp/crunch-run.%%J.out", "-e", "/tmp/crunch-run.%%J.err", "-J", "%U", "-n", "%C", "-D", "%MMB", "-R", "rusage[mem=%MMB:tmp=%TMB] span[hosts=1]", "-R", "select[mem>=%MMB]", "-R", "select[tmp>=%TMB]", "-R", "select[ncpus>=%C]"]
+ #
+ # If ["-We", "%W"] or ["-W", "%W"] appear in this argument
+ # list, and MaxRunTimeDefault is not set (see below), both of
+ # those arguments will be dropped from the argument list when
+ # running a container that has no max_run_time value.
+ BsubArgumentsList: ["-o", "/tmp/crunch-run.%%J.out", "-e", "/tmp/crunch-run.%%J.err", "-J", "%U", "-n", "%C", "-D", "%MMB", "-R", "rusage[mem=%MMB:tmp=%TMB] span[hosts=1]", "-R", "select[mem>=%MMB]", "-R", "select[tmp>=%TMB]", "-R", "select[ncpus>=%C]", "-We", "%W"]
# Arguments that will be appended to the bsub command line
# when submitting Arvados containers as LSF jobs with
@@ -1400,6 +1408,19 @@ Clusters:
# Arvados LSF dispatcher runs ("submission host").
BsubSudoUser: "crunch"
+ # When passing the scheduling_constraints.max_run_time value
+ # to LSF via "%W", add this much time to account for
+ # crunch-run startup/shutdown overhead.
+ MaxRunTimeOverhead: 5m
+
+ # If non-zero, MaxRunTimeDefault is used as the default value
+ # for max_run_time for containers that do not specify a time
+ # limit. MaxRunTimeOverhead will be added to this.
+ #
+ # Example:
+ # MaxRunTimeDefault: 2h
+ MaxRunTimeDefault: 0
+
JobsAPI:
# Enable the legacy 'jobs' API (crunch v1). This value must be a string.
#
diff --git a/lib/lsf/dispatch.go b/lib/lsf/dispatch.go
index d1408d23cb..897e5803f2 100644
--- a/lib/lsf/dispatch.go
+++ b/lib/lsf/dispatch.go
@@ -306,6 +306,15 @@ func (disp *dispatcher) bsubArgs(container arvados.Container) ([]string, error)
container.RuntimeConstraints.KeepCacheRAM+
int64(disp.Cluster.Containers.ReserveExtraRAM)) / 1048576))
+ maxruntime := time.Duration(container.SchedulingParameters.MaxRunTime) * time.Second
+ if maxruntime == 0 {
+ maxruntime = disp.Cluster.Containers.LSF.MaxRunTimeDefault.Duration()
+ }
+ if maxruntime > 0 {
+ maxruntime += disp.Cluster.Containers.LSF.MaxRunTimeOverhead.Duration()
+ }
+ maxrunminutes := int64(math.Ceil(float64(maxruntime.Seconds()) / 60))
+
repl := map[string]string{
"%%": "%",
"%C": fmt.Sprintf("%d", vcpus),
@@ -313,6 +322,7 @@ func (disp *dispatcher) bsubArgs(container arvados.Container) ([]string, error)
"%T": fmt.Sprintf("%d", tmp),
"%U": container.UUID,
"%G": fmt.Sprintf("%d", container.RuntimeConstraints.CUDA.DeviceCount),
+ "%W": fmt.Sprintf("%d", maxrunminutes),
}
re := regexp.MustCompile(`%.`)
@@ -321,7 +331,16 @@ func (disp *dispatcher) bsubArgs(container arvados.Container) ([]string, error)
if container.RuntimeConstraints.CUDA.DeviceCount > 0 {
argumentTemplate = append(argumentTemplate, disp.Cluster.Containers.LSF.BsubCUDAArguments...)
}
- for _, a := range argumentTemplate {
+ for idx, a := range argumentTemplate {
+ if idx > 0 && (argumentTemplate[idx-1] == "-W" || argumentTemplate[idx-1] == "-We") && a == "%W" && maxrunminutes == 0 {
+ // LSF docs don't specify an argument to "-W"
+ // or "-We" that indicates "unknown", so
+ // instead we drop the "-W %W" part of the
+ // command line entirely when max runtime is
+ // unknown.
+ args = args[:len(args)-1]
+ continue
+ }
args = append(args, re.ReplaceAllStringFunc(a, func(s string) string {
subst := repl[s]
if len(subst) == 0 {
diff --git a/lib/lsf/dispatch_test.go b/lib/lsf/dispatch_test.go
index cd41071d2c..e1e0bcae31 100644
--- a/lib/lsf/dispatch_test.go
+++ b/lib/lsf/dispatch_test.go
@@ -34,6 +34,7 @@ type suite struct {
crTooBig arvados.ContainerRequest
crPending arvados.ContainerRequest
crCUDARequest arvados.ContainerRequest
+ crMaxRunTime arvados.ContainerRequest
}
func (s *suite) TearDownTest(c *check.C) {
@@ -116,6 +117,25 @@ func (s *suite) SetUpTest(c *check.C) {
})
c.Assert(err, check.IsNil)
+ err = arvados.NewClientFromEnv().RequestAndDecode(&s.crMaxRunTime, "POST", "arvados/v1/container_requests", nil, map[string]interface{}{
+ "container_request": map[string]interface{}{
+ "runtime_constraints": arvados.RuntimeConstraints{
+ RAM: 1000000,
+ VCPUs: 1,
+ },
+ "scheduling_parameters": arvados.SchedulingParameters{
+ MaxRunTime: 124,
+ },
+ "container_image": arvadostest.DockerImage112PDH,
+ "command": []string{"sleep", "123"},
+ "mounts": map[string]arvados.Mount{"/mnt/out": {Kind: "tmp", Capacity: 1000}},
+ "output_path": "/mnt/out",
+ "state": arvados.ContainerRequestStateCommitted,
+ "priority": 1,
+ "container_count_max": 1,
+ },
+ })
+ c.Assert(err, check.IsNil)
}
type lsfstub struct {
@@ -141,12 +161,7 @@ func (stub lsfstub) stubCommand(s *suite, c *check.C) func(prog string, args ...
}
switch prog {
case "bsub":
- defaultArgs := s.disp.Cluster.Containers.LSF.BsubArgumentsList
- if args[5] == s.crCUDARequest.ContainerUUID {
- c.Assert(len(args), check.Equals, len(defaultArgs)+len(s.disp.Cluster.Containers.LSF.BsubCUDAArguments))
- } else {
- c.Assert(len(args), check.Equals, len(defaultArgs))
- }
+ c.Assert(len(args) > 5, check.Equals, true)
// %%J must have been rewritten to %J
c.Check(args[1], check.Equals, "/tmp/crunch-run.%J.out")
args = args[4:]
@@ -204,6 +219,21 @@ func (stub lsfstub) stubCommand(s *suite, c *check.C) func(prog string, args ...
fakejobq[nextjobid] = args[1]
nextjobid++
mtx.Unlock()
+ case s.crMaxRunTime.ContainerUUID:
+ c.Check(args, check.DeepEquals, []string{
+ "-J", s.crMaxRunTime.ContainerUUID,
+ "-n", "1",
+ "-D", "257MB",
+ "-R", "rusage[mem=257MB:tmp=2304MB] span[hosts=1]",
+ "-R", "select[mem>=257MB]",
+ "-R", "select[tmp>=2304MB]",
+ "-R", "select[ncpus>=1]",
+ "-We", "8", // 124s + 5m overhead + roundup = 8m
+ })
+ mtx.Lock()
+ fakejobq[nextjobid] = args[1]
+ nextjobid++
+ mtx.Unlock()
default:
c.Errorf("unexpected uuid passed to bsub: args %q", args)
return exec.Command("false")
diff --git a/sdk/go/arvados/config.go b/sdk/go/arvados/config.go
index e39a1ff0aa..a0caea4f38 100644
--- a/sdk/go/arvados/config.go
+++ b/sdk/go/arvados/config.go
@@ -561,9 +561,11 @@ type ContainersConfig struct {
}
}
LSF struct {
- BsubSudoUser string
- BsubArgumentsList []string
- BsubCUDAArguments []string
+ BsubSudoUser string
+ BsubArgumentsList []string
+ BsubCUDAArguments []string
+ MaxRunTimeOverhead Duration
+ MaxRunTimeDefault Duration
}
}
diff --git a/services/api/app/models/container_request.rb b/services/api/app/models/container_request.rb
index d72f00edc8..3a7dfdd81f 100644
--- a/services/api/app/models/container_request.rb
+++ b/services/api/app/models/container_request.rb
@@ -467,8 +467,9 @@ class ContainerRequest < ArvadosModel
def validate_scheduling_parameters
if self.state == Committed
- if scheduling_parameters.include? 'partitions' and
- (!scheduling_parameters['partitions'].is_a?(Array) ||
+ if scheduling_parameters.include?('partitions') and
+ !scheduling_parameters['partitions'].nil? and
+ (!scheduling_parameters['partitions'].is_a?(Array) ||
scheduling_parameters['partitions'].reject{|x| !x.is_a?(String)}.size !=
scheduling_parameters['partitions'].size)
errors.add :scheduling_parameters, "partitions must be an array of strings"
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list