16838: Merge branch 'master' into 16838-probe-metrics
[arvados.git] / lib / dispatchcloud / node_size_test.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package dispatchcloud
6
7 import (
8         "git.arvados.org/arvados.git/sdk/go/arvados"
9         check "gopkg.in/check.v1"
10 )
11
12 var _ = check.Suite(&NodeSizeSuite{})
13
14 const GiB = arvados.ByteSize(1 << 30)
15
16 type NodeSizeSuite struct{}
17
18 func (*NodeSizeSuite) TestChooseNotConfigured(c *check.C) {
19         _, err := ChooseInstanceType(&arvados.Cluster{}, &arvados.Container{
20                 RuntimeConstraints: arvados.RuntimeConstraints{
21                         RAM:   1234567890,
22                         VCPUs: 2,
23                 },
24         })
25         c.Check(err, check.Equals, ErrInstanceTypesNotConfigured)
26 }
27
28 func (*NodeSizeSuite) TestChooseUnsatisfiable(c *check.C) {
29         checkUnsatisfiable := func(ctr *arvados.Container) {
30                 _, err := ChooseInstanceType(&arvados.Cluster{InstanceTypes: map[string]arvados.InstanceType{
31                         "small1": {Price: 1.1, RAM: 1000000000, VCPUs: 2, Name: "small1"},
32                         "small2": {Price: 2.2, RAM: 2000000000, VCPUs: 4, Name: "small2"},
33                         "small4": {Price: 4.4, RAM: 4000000000, VCPUs: 8, Name: "small4", Scratch: GiB},
34                 }}, ctr)
35                 c.Check(err, check.FitsTypeOf, ConstraintsNotSatisfiableError{})
36         }
37
38         for _, rc := range []arvados.RuntimeConstraints{
39                 {RAM: 9876543210, VCPUs: 2},
40                 {RAM: 1234567890, VCPUs: 20},
41                 {RAM: 1234567890, VCPUs: 2, KeepCacheRAM: 9876543210},
42         } {
43                 checkUnsatisfiable(&arvados.Container{RuntimeConstraints: rc})
44         }
45         checkUnsatisfiable(&arvados.Container{
46                 Mounts:             map[string]arvados.Mount{"/tmp": {Kind: "tmp", Capacity: int64(2 * GiB)}},
47                 RuntimeConstraints: arvados.RuntimeConstraints{RAM: 12345, VCPUs: 1},
48         })
49 }
50
51 func (*NodeSizeSuite) TestChoose(c *check.C) {
52         for _, menu := range []map[string]arvados.InstanceType{
53                 {
54                         "costly": {Price: 4.4, RAM: 4000000000, VCPUs: 8, Scratch: 2 * GiB, Name: "costly"},
55                         "best":   {Price: 2.2, RAM: 2000000000, VCPUs: 4, Scratch: 2 * GiB, Name: "best"},
56                         "small":  {Price: 1.1, RAM: 1000000000, VCPUs: 2, Scratch: 2 * GiB, Name: "small"},
57                 },
58                 {
59                         "costly":     {Price: 4.4, RAM: 4000000000, VCPUs: 8, Scratch: 2 * GiB, Name: "costly"},
60                         "goodenough": {Price: 2.2, RAM: 2000000000, VCPUs: 4, Scratch: 2 * GiB, Name: "goodenough"},
61                         "best":       {Price: 2.2, RAM: 4000000000, VCPUs: 4, Scratch: 2 * GiB, Name: "best"},
62                         "small":      {Price: 1.1, RAM: 1000000000, VCPUs: 2, Scratch: 2 * GiB, Name: "small"},
63                 },
64                 {
65                         "small":      {Price: 1.1, RAM: 1000000000, VCPUs: 2, Scratch: 2 * GiB, Name: "small"},
66                         "goodenough": {Price: 2.2, RAM: 2000000000, VCPUs: 4, Scratch: 2 * GiB, Name: "goodenough"},
67                         "best":       {Price: 2.2, RAM: 4000000000, VCPUs: 4, Scratch: 2 * GiB, Name: "best"},
68                         "costly":     {Price: 4.4, RAM: 4000000000, VCPUs: 8, Scratch: 2 * GiB, Name: "costly"},
69                 },
70                 {
71                         "small":  {Price: 1.1, RAM: 1000000000, VCPUs: 2, Scratch: GiB, Name: "small"},
72                         "nearly": {Price: 2.2, RAM: 2000000000, VCPUs: 4, Scratch: GiB, Name: "nearly"},
73                         "best":   {Price: 3.3, RAM: 4000000000, VCPUs: 4, Scratch: 2 * GiB, Name: "best"},
74                         "costly": {Price: 4.4, RAM: 4000000000, VCPUs: 8, Scratch: 2 * GiB, Name: "costly"},
75                 },
76         } {
77                 best, err := ChooseInstanceType(&arvados.Cluster{InstanceTypes: menu}, &arvados.Container{
78                         Mounts: map[string]arvados.Mount{
79                                 "/tmp": {Kind: "tmp", Capacity: 2 * int64(GiB)},
80                         },
81                         RuntimeConstraints: arvados.RuntimeConstraints{
82                                 VCPUs:        2,
83                                 RAM:          987654321,
84                                 KeepCacheRAM: 123456789,
85                         },
86                 })
87                 c.Check(err, check.IsNil)
88                 c.Check(best.Name, check.Equals, "best")
89                 c.Check(best.RAM >= 1234567890, check.Equals, true)
90                 c.Check(best.VCPUs >= 2, check.Equals, true)
91                 c.Check(best.Scratch >= 2*GiB, check.Equals, true)
92         }
93 }
94
95 func (*NodeSizeSuite) TestChoosePreemptable(c *check.C) {
96         menu := map[string]arvados.InstanceType{
97                 "costly":      {Price: 4.4, RAM: 4000000000, VCPUs: 8, Scratch: 2 * GiB, Preemptible: true, Name: "costly"},
98                 "almost best": {Price: 2.2, RAM: 2000000000, VCPUs: 4, Scratch: 2 * GiB, Name: "almost best"},
99                 "best":        {Price: 2.2, RAM: 2000000000, VCPUs: 4, Scratch: 2 * GiB, Preemptible: true, Name: "best"},
100                 "small":       {Price: 1.1, RAM: 1000000000, VCPUs: 2, Scratch: 2 * GiB, Preemptible: true, Name: "small"},
101         }
102         best, err := ChooseInstanceType(&arvados.Cluster{InstanceTypes: menu}, &arvados.Container{
103                 Mounts: map[string]arvados.Mount{
104                         "/tmp": {Kind: "tmp", Capacity: 2 * int64(GiB)},
105                 },
106                 RuntimeConstraints: arvados.RuntimeConstraints{
107                         VCPUs:        2,
108                         RAM:          987654321,
109                         KeepCacheRAM: 123456789,
110                 },
111                 SchedulingParameters: arvados.SchedulingParameters{
112                         Preemptible: true,
113                 },
114         })
115         c.Check(err, check.IsNil)
116         c.Check(best.Name, check.Equals, "best")
117         c.Check(best.RAM >= 1234567890, check.Equals, true)
118         c.Check(best.VCPUs >= 2, check.Equals, true)
119         c.Check(best.Scratch >= 2*GiB, check.Equals, true)
120         c.Check(best.Preemptible, check.Equals, true)
121 }
122
123 func (*NodeSizeSuite) TestScratchForDockerImage(c *check.C) {
124         n := EstimateScratchSpace(&arvados.Container{
125                 ContainerImage: "d5025c0f29f6eef304a7358afa82a822+342",
126         })
127         // Actual image is 371.1 MiB (according to workbench)
128         // Estimated size is 384 MiB (402653184 bytes)
129         // Want to reserve 2x the estimated size, so 805306368 bytes
130         c.Check(n, check.Equals, int64(805306368))
131
132         n = EstimateScratchSpace(&arvados.Container{
133                 ContainerImage: "d5025c0f29f6eef304a7358afa82a822+-342",
134         })
135         // Parse error will return 0
136         c.Check(n, check.Equals, int64(0))
137
138         n = EstimateScratchSpace(&arvados.Container{
139                 ContainerImage: "d5025c0f29f6eef304a7358afa82a822+34",
140         })
141         // Short manifest will return 0
142         c.Check(n, check.Equals, int64(0))
143 }