X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/7fd377c676394477f027869dfbdb125ac6ed26f0..aa208f2ea4f7d0bc05628399cde30fd9c3747a8c:/lib/crunchrun/crunchrun_test.go diff --git a/lib/crunchrun/crunchrun_test.go b/lib/crunchrun/crunchrun_test.go index 1f4681e3a7..aaba1c4204 100644 --- a/lib/crunchrun/crunchrun_test.go +++ b/lib/crunchrun/crunchrun_test.go @@ -12,6 +12,7 @@ import ( "fmt" "io" "io/ioutil" + "log" "os" "os/exec" "regexp" @@ -22,6 +23,7 @@ import ( "testing" "time" + "git.arvados.org/arvados.git/lib/cloud" "git.arvados.org/arvados.git/lib/cmd" "git.arvados.org/arvados.git/sdk/go/arvados" "git.arvados.org/arvados.git/sdk/go/arvadosclient" @@ -595,7 +597,7 @@ func (s *TestSuite) TestUpdateContainerRunning(c *C) { cr, err := NewContainerRunner(s.client, api, kc, "zzzzz-zzzzz-zzzzzzzzzzzzzzz") c.Assert(err, IsNil) - err = cr.UpdateContainerRunning() + err = cr.UpdateContainerRunning("") c.Check(err, IsNil) c.Check(api.Content[0]["container"].(arvadosclient.Dict)["state"], Equals, "Running") @@ -896,6 +898,42 @@ func (s *TestSuite) TestLogVersionAndRuntime(c *C) { c.Check(s.api.Logs["crunch-run"].String(), Matches, `(?ms).*Using container runtime: stub.*`) } +func (s *TestSuite) TestCommitNodeInfoBeforeStart(c *C) { + var collection_create, container_update arvadosclient.Dict + s.fullRunHelper(c, `{ + "command": ["true"], + "container_image": "`+arvadostest.DockerImage112PDH+`", + "cwd": ".", + "environment": {}, + "mounts": {"/tmp": {"kind": "tmp"} }, + "output_path": "/tmp", + "priority": 1, + "runtime_constraints": {}, + "state": "Locked", + "uuid": "zzzzz-dz642-202301121543210" + }`, nil, 0, + func() { + collection_create = s.api.CalledWith("ensure_unique_name", true) + container_update = s.api.CalledWith("container.state", "Running") + }) + + c.Assert(collection_create, NotNil) + log_collection := collection_create["collection"].(arvadosclient.Dict) + c.Check(log_collection["name"], Equals, "logs for zzzzz-dz642-202301121543210") + manifest_text := log_collection["manifest_text"].(string) + // We check that the file size is at least two digits as an easy way to + // check the file isn't empty. + c.Check(manifest_text, Matches, `\. .+ \d+:\d{2,}:node-info\.txt( .+)?\n`) + c.Check(manifest_text, Matches, `\. .+ \d+:\d{2,}:node\.json( .+)?\n`) + + c.Assert(container_update, NotNil) + // As of Arvados 2.5.0, the container update must specify its log in PDH + // format for the API server to propagate it to container requests, which + // is what we care about for this test. + expect_pdh := fmt.Sprintf("%x+%d", md5.Sum([]byte(manifest_text)), len(manifest_text)) + c.Check(container_update["container"].(arvadosclient.Dict)["log"], Equals, expect_pdh) +} + func (s *TestSuite) TestContainerRecordLog(c *C) { s.fullRunHelper(c, `{ "command": ["sleep", "1"], @@ -2080,6 +2118,60 @@ func (s *TestSuite) TestSecretTextMountPoint(c *C) { c.Check(s.runner.ContainerArvClient.(*ArvTestClient).CalledWith("collection.manifest_text", ". acbd18db4cc2f85cedef654fccc4a4d8+3 0:3:foo.txt\n"), NotNil) } +func (s *TestSuite) TestCalculateCost(c *C) { + defer func(s string) { lockdir = s }(lockdir) + lockdir = c.MkDir() + now := time.Now() + cr := s.runner + cr.costStartTime = now.Add(-time.Hour) + var logbuf bytes.Buffer + cr.CrunchLog.Immediate = log.New(&logbuf, "", 0) + + // if there's no InstanceType env var, cost is calculated as 0 + os.Unsetenv("InstanceType") + cost := cr.calculateCost(now) + c.Check(cost, Equals, 0.0) + + // with InstanceType env var and loadPrices() hasn't run (or + // hasn't found any data), cost is calculated based on + // InstanceType env var + os.Setenv("InstanceType", `{"Price":1.2}`) + defer os.Unsetenv("InstanceType") + cost = cr.calculateCost(now) + c.Check(cost, Equals, 1.2) + + // first update tells us the spot price was $1/h until 30 + // minutes ago when it increased to $2/h + j, err := json.Marshal([]cloud.InstancePrice{ + {StartTime: now.Add(-4 * time.Hour), Price: 1.0}, + {StartTime: now.Add(-time.Hour / 2), Price: 2.0}, + }) + c.Assert(err, IsNil) + os.WriteFile(lockdir+"/"+pricesfile, j, 0777) + cr.loadPrices() + cost = cr.calculateCost(now) + c.Check(cost, Equals, 1.5) + + // next update (via --list + SIGUSR2) tells us the spot price + // increased to $3/h 15 minutes ago + j, err = json.Marshal([]cloud.InstancePrice{ + {StartTime: now.Add(-time.Hour / 3), Price: 2.0}, // dup of -time.Hour/2 price + {StartTime: now.Add(-time.Hour / 4), Price: 3.0}, + }) + c.Assert(err, IsNil) + os.WriteFile(lockdir+"/"+pricesfile, j, 0777) + cr.loadPrices() + cost = cr.calculateCost(now) + c.Check(cost, Equals, 1.0/2+2.0/4+3.0/4) + + cost = cr.calculateCost(now.Add(-time.Hour / 2)) + c.Check(cost, Equals, 0.5) + + c.Logf("%s", logbuf.String()) + c.Check(logbuf.String(), Matches, `(?ms).*Instance price changed to 1\.00 at 20.* changed to 2\.00 .* changed to 3\.00 .*`) + c.Check(logbuf.String(), Not(Matches), `(?ms).*changed to 2\.00 .* changed to 2\.00 .*`) +} + type FakeProcess struct { cmdLine []string }