+ c.Check(best.Preemptible, check.Equals, true)
+}
+
+func (*NodeSizeSuite) TestScratchForDockerImage(c *check.C) {
+ n := EstimateScratchSpace(&arvados.Container{
+ ContainerImage: "d5025c0f29f6eef304a7358afa82a822+342",
+ })
+ // Actual image is 371.1 MiB (according to workbench)
+ // Estimated size is 384 MiB (402653184 bytes)
+ // Want to reserve 2x the estimated size, so 805306368 bytes
+ c.Check(n, check.Equals, int64(805306368))
+
+ n = EstimateScratchSpace(&arvados.Container{
+ ContainerImage: "d5025c0f29f6eef304a7358afa82a822+-342",
+ })
+ // Parse error will return 0
+ c.Check(n, check.Equals, int64(0))
+
+ n = EstimateScratchSpace(&arvados.Container{
+ ContainerImage: "d5025c0f29f6eef304a7358afa82a822+34",
+ })
+ // Short manifest will return 0
+ c.Check(n, check.Equals, int64(0))
+}
+
+func (*NodeSizeSuite) TestChooseGPU(c *check.C) {
+ menu := map[string]arvados.InstanceType{
+ "costly": {Price: 4.4, RAM: 4000000000, VCPUs: 8, Scratch: 2 * GiB, Name: "costly", CUDA: arvados.CUDAFeatures{DeviceCount: 2, HardwareCapability: "9.0", DriverVersion: "11.0"}},
+ "low_capability": {Price: 2.1, RAM: 2000000000, VCPUs: 4, Scratch: 2 * GiB, Name: "low_capability", CUDA: arvados.CUDAFeatures{DeviceCount: 1, HardwareCapability: "8.0", DriverVersion: "11.0"}},
+ "best": {Price: 2.2, RAM: 2000000000, VCPUs: 4, Scratch: 2 * GiB, Name: "best", CUDA: arvados.CUDAFeatures{DeviceCount: 1, HardwareCapability: "9.0", DriverVersion: "11.0"}},
+ "low_driver": {Price: 2.1, RAM: 2000000000, VCPUs: 4, Scratch: 2 * GiB, Name: "low_driver", CUDA: arvados.CUDAFeatures{DeviceCount: 1, HardwareCapability: "9.0", DriverVersion: "10.0"}},
+ "cheap_gpu": {Price: 2.0, RAM: 2000000000, VCPUs: 4, Scratch: 2 * GiB, Name: "cheap_gpu", CUDA: arvados.CUDAFeatures{DeviceCount: 1, HardwareCapability: "8.0", DriverVersion: "10.0"}},
+ "invalid_gpu": {Price: 1.9, RAM: 2000000000, VCPUs: 4, Scratch: 2 * GiB, Name: "invalid_gpu", CUDA: arvados.CUDAFeatures{DeviceCount: 1, HardwareCapability: "12.0.12", DriverVersion: "12.0.12"}},
+ "non_gpu": {Price: 1.1, RAM: 2000000000, VCPUs: 4, Scratch: 2 * GiB, Name: "non_gpu"},
+ }
+
+ type GPUTestCase struct {
+ CUDA arvados.CUDARuntimeConstraints
+ SelectedInstance string
+ }
+ cases := []GPUTestCase{
+ GPUTestCase{
+ CUDA: arvados.CUDARuntimeConstraints{
+ DeviceCount: 1,
+ HardwareCapability: "9.0",
+ DriverVersion: "11.0",
+ },
+ SelectedInstance: "best",
+ },
+ GPUTestCase{
+ CUDA: arvados.CUDARuntimeConstraints{
+ DeviceCount: 2,
+ HardwareCapability: "9.0",
+ DriverVersion: "11.0",
+ },
+ SelectedInstance: "costly",
+ },
+ GPUTestCase{
+ CUDA: arvados.CUDARuntimeConstraints{
+ DeviceCount: 1,
+ HardwareCapability: "8.0",
+ DriverVersion: "11.0",
+ },
+ SelectedInstance: "low_capability",
+ },
+ GPUTestCase{
+ CUDA: arvados.CUDARuntimeConstraints{
+ DeviceCount: 1,
+ HardwareCapability: "9.0",
+ DriverVersion: "10.0",
+ },
+ SelectedInstance: "low_driver",
+ },
+ GPUTestCase{
+ CUDA: arvados.CUDARuntimeConstraints{
+ DeviceCount: 1,
+ HardwareCapability: "",
+ DriverVersion: "10.0",
+ },
+ SelectedInstance: "",
+ },
+ GPUTestCase{
+ CUDA: arvados.CUDARuntimeConstraints{
+ DeviceCount: 0,
+ HardwareCapability: "9.0",
+ DriverVersion: "11.0",
+ },
+ SelectedInstance: "non_gpu",
+ },
+ }
+
+ for _, tc := range cases {
+ best, err := ChooseInstanceType(&arvados.Cluster{InstanceTypes: menu}, &arvados.Container{
+ Mounts: map[string]arvados.Mount{
+ "/tmp": {Kind: "tmp", Capacity: 2 * int64(GiB)},
+ },
+ RuntimeConstraints: arvados.RuntimeConstraints{
+ VCPUs: 2,
+ RAM: 987654321,
+ KeepCacheRAM: 123456789,
+ CUDA: tc.CUDA,
+ },
+ })
+ if best.Name != "" {
+ c.Check(err, check.IsNil)
+ c.Check(best.Name, check.Equals, tc.SelectedInstance)
+ } else {
+ c.Check(err, check.Not(check.IsNil))
+ }
+ }