Skip to content

Commit b096eca

Browse files
feat(instance): support scratch volumes in servers (#3345)
Co-authored-by: Nathanael Demacon <[email protected]>
1 parent 0e50e1e commit b096eca

File tree

6 files changed

+2969
-4
lines changed

6 files changed

+2969
-4
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ require (
2424
github.com/moby/buildkit v0.11.6
2525
github.com/opencontainers/go-digest v1.0.0
2626
github.com/pkg/errors v0.9.1
27-
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.20.0.20230911082817-45ad1e03b1bb
27+
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.21
2828
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
2929
github.com/spf13/cobra v1.7.0
3030
github.com/spf13/pflag v1.0.5

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -491,8 +491,8 @@ github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncj
491491
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
492492
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI=
493493
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs=
494-
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.20.0.20230911082817-45ad1e03b1bb h1:symGjmphE602x27B1kY17r2BamxUaO5alk8y/Vw5N5M=
495-
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.20.0.20230911082817-45ad1e03b1bb/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
494+
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.21 h1:yWfiTPwYxB0l5fGMhl/G+liULugVIHD9AU77iNLrURQ=
495+
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.21/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
496496
github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8=
497497
github.com/secure-systems-lab/go-securesystemslib v0.4.0 h1:b23VGrQhTA8cN2CbBw7/FulN9fTtqYUdS5+Oxzt+DUE=
498498
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=

internal/namespaces/instance/v1/custom_server_create.go

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,11 @@ func instanceServerCreateRun(ctx context.Context, argsI interface{}) (i interfac
313313
serverReq.Volumes = sanitizeVolumeMap(serverReq.Name, volumes)
314314
}
315315

316+
// Add default volumes to server, ex: scratch storage for GPU servers
317+
if serverType != nil {
318+
serverReq.Volumes = addDefaultVolumes(serverType, serverReq.Volumes)
319+
}
320+
316321
//
317322
// BootType.
318323
//
@@ -433,6 +438,46 @@ func instanceServerCreateRun(ctx context.Context, argsI interface{}) (i interfac
433438
return server, nil
434439
}
435440

441+
func addDefaultVolumes(serverType *instance.ServerType, volumes map[string]*instance.VolumeServerTemplate) map[string]*instance.VolumeServerTemplate {
442+
needScratch := false
443+
hasScratch := false
444+
defaultVolumes := []*instance.VolumeServerTemplate(nil)
445+
if serverType.ScratchStorageMaxSize != nil && *serverType.ScratchStorageMaxSize > 0 {
446+
needScratch = true
447+
}
448+
for _, volume := range volumes {
449+
if volume.VolumeType == instance.VolumeVolumeTypeScratch {
450+
hasScratch = true
451+
}
452+
}
453+
454+
if needScratch && !hasScratch {
455+
defaultVolumes = append(defaultVolumes, &instance.VolumeServerTemplate{
456+
Name: scw.StringPtr("default-cli-scratch-volume"),
457+
Size: serverType.ScratchStorageMaxSize,
458+
VolumeType: instance.VolumeVolumeTypeScratch,
459+
})
460+
}
461+
462+
if defaultVolumes != nil {
463+
if volumes == nil {
464+
volumes = make(map[string]*instance.VolumeServerTemplate)
465+
}
466+
maxKey := 1
467+
for k := range volumes {
468+
key, err := strconv.Atoi(k)
469+
if err == nil && key > maxKey {
470+
maxKey = key
471+
}
472+
}
473+
for i, vol := range defaultVolumes {
474+
volumes[strconv.Itoa(maxKey+i)] = vol
475+
}
476+
}
477+
478+
return volumes
479+
}
480+
436481
// buildVolumes creates the initial volume map.
437482
// It is not the definitive one, it will be mutated all along the process.
438483
func buildVolumes(api *instance.API, zone scw.Zone, serverName, rootVolume string, additionalVolumes []string) (map[string]*instance.VolumeServerTemplate, error) {
@@ -473,7 +518,7 @@ func buildVolumes(api *instance.API, zone scw.Zone, serverName, rootVolume strin
473518
// Volumes definition must be through multiple arguments (eg: volumes.0="l:20GB" volumes.1="b:100GB")
474519
//
475520
// A valid volume format is either
476-
// - a "creation" format: ^((local|l|block|b):)?\d+GB?$ (size is handled by go-humanize, so other sizes are supported)
521+
// - a "creation" format: ^((local|l|block|b|scratch|s):)?\d+GB?$ (size is handled by go-humanize, so other sizes are supported)
477522
// - a "creation" format with a snapshot id: l:<uuid> b:<uuid>
478523
// - a UUID format
479524
func buildVolumeTemplate(api *instance.API, zone scw.Zone, flagV string) (*instance.VolumeServerTemplate, error) {
@@ -488,6 +533,8 @@ func buildVolumeTemplate(api *instance.API, zone scw.Zone, flagV string) (*insta
488533
vt.VolumeType = instance.VolumeVolumeTypeLSSD
489534
case "b", "block":
490535
vt.VolumeType = instance.VolumeVolumeTypeBSSD
536+
case "s", "scratch":
537+
vt.VolumeType = instance.VolumeVolumeTypeScratch
491538
default:
492539
return nil, fmt.Errorf("invalid volume type %s in %s volume", parts[0], flagV)
493540
}

internal/namespaces/instance/v1/custom_server_create_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package instance
22

33
import (
4+
"fmt"
45
"testing"
56

67
"github.com/alecthomas/assert"
@@ -485,3 +486,29 @@ func Test_CreateServerErrors(t *testing.T) {
485486
),
486487
}))
487488
}
489+
490+
func Test_CreateServerScratchStorage(t *testing.T) {
491+
t.Run("Default scratch storage", core.Test(&core.TestConfig{
492+
Commands: GetCommands(),
493+
Cmd: "scw instance server create type=H100-1-80G image=ubuntu_jammy_gpu_os_12",
494+
Check: core.TestCheckCombine(
495+
core.TestCheckGolden(),
496+
func(t *testing.T, ctx *core.CheckFuncCtx) {
497+
fmt.Println(ctx.LogBuffer)
498+
},
499+
core.TestCheckExitCode(0),
500+
func(t *testing.T, ctx *core.CheckFuncCtx) {
501+
server, isServer := ctx.Result.(*instance.Server)
502+
if !isServer {
503+
t.Fatalf("Result is not a server")
504+
}
505+
additionalVolume, exist := server.Volumes["1"]
506+
if !exist {
507+
t.Fatalf("Expected an additional scratch volume, found none")
508+
}
509+
assert.Equal(t, additionalVolume.VolumeType, instance.VolumeServerVolumeTypeScratch)
510+
},
511+
),
512+
DisableParallel: true,
513+
}))
514+
}

0 commit comments

Comments
 (0)