diff --git a/mantle/platform/api/gcloud/compute.go b/mantle/platform/api/gcloud/compute.go index af6c047d63..b2e9606253 100644 --- a/mantle/platform/api/gcloud/compute.go +++ b/mantle/platform/api/gcloud/compute.go @@ -17,6 +17,7 @@ package gcloud import ( "crypto/rand" "fmt" + "strconv" "strings" "time" @@ -33,8 +34,56 @@ func (a *API) vmname() string { return fmt.Sprintf("%s-%x", a.options.BaseName, b) } +// ["local-ssd:interface=NVME,size=375"] +func ParseDiskSpec(spec string, zone string) (*compute.AttachedDisk, error) { + split := strings.Split(spec, ":") + var disktype string + var diskinterface string + var disksize string + var size int64 + var err error + disk_ps := "PERSISTENT" + if len(split) == 1 { + disktype = split[0] + } else if len(split) == 2 { + disktype = split[0] + for _, opt := range strings.Split(split[1], ",") { + if strings.HasPrefix(opt, "interface=") { + diskinterface = strings.TrimPrefix(opt, "interface=") + if diskinterface == "" || (diskinterface != "NVME" && diskinterface != "SCSI"){ + return nil, fmt.Errorf("invalid interface opt %s", opt) + } + } else if strings.HasPrefix(opt, "size=") { + disksize = strings.TrimPrefix(opt, "size=") + size, err = strconv.ParseInt(disksize, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid size opt %s", opt) + } + } else { + return nil, fmt.Errorf("unknown disk option %s", opt) + } + } + } else { + return nil, fmt.Errorf("invalid disk spec %s", spec) + } + + if disktype == "local-ssd" { + disk_ps = "SCRATCH" + } + return &compute.AttachedDisk{ + AutoDelete: true, + Boot: false, + Type: disk_ps, + Interface: diskinterface, + InitializeParams: &compute.AttachedDiskInitializeParams{ + DiskType: "/zones/" + zone + "/diskTypes/" + disktype, + DiskSizeGb: size, + }, + }, nil +} + // Taken from: https://github.com/golang/build/blob/master/buildlet/gce.go -func (a *API) mkinstance(userdata, name string, keys []*agent.Key, useServiceAcct bool) *compute.Instance { +func (a *API) mkinstance(userdata, name string, keys []*agent.Key, additionalDisks []string, useServiceAcct bool) (*compute.Instance, error) { mantle := "mantle" metadataItems := []*compute.MetadataItems{ { @@ -120,14 +169,24 @@ func (a *API) mkinstance(userdata, name string, keys []*agent.Key, useServiceAcc OnHostMaintenance: "TERMINATE", } } + // attach aditional disk + if len(additionalDisks) > 0 { + for _, spec := range additionalDisks { + disk, err := ParseDiskSpec(spec, a.options.Zone) + if err != nil { + return nil, fmt.Errorf("failed to parse spec: %s\n", spec) + } + instance.Disks = append(instance.Disks, disk) + } + } return instance } // CreateInstance creates a Google Compute Engine instance. -func (a *API) CreateInstance(userdata string, keys []*agent.Key, useServiceAcct bool) (*compute.Instance, error) { +func (a *API) CreateInstance(userdata string, keys []*agent.Key, additionalDisks []string, useServiceAcct bool) (*compute.Instance, error) { name := a.vmname() - inst := a.mkinstance(userdata, name, keys, useServiceAcct) + inst := a.mkinstance(userdata, name, keys, additionalDisks, useServiceAcct) plog.Debugf("Creating instance %q", name) diff --git a/mantle/platform/machine/gcloud/cluster.go b/mantle/platform/machine/gcloud/cluster.go index 80347f0c10..aca48cb7eb 100644 --- a/mantle/platform/machine/gcloud/cluster.go +++ b/mantle/platform/machine/gcloud/cluster.go @@ -37,9 +37,6 @@ func (gc *cluster) NewMachine(userdata *conf.UserData) (platform.Machine, error) } func (gc *cluster) NewMachineWithOptions(userdata *conf.UserData, options platform.MachineOptions) (platform.Machine, error) { - if len(options.AdditionalDisks) > 0 { - return nil, errors.New("platform gcp does not yet support additional disks") - } if options.MultiPathDisk { return nil, errors.New("platform gcp does not support multipathed disks") } @@ -69,7 +66,7 @@ func (gc *cluster) NewMachineWithOptions(userdata *conf.UserData, options platfo } } - instance, err := gc.flight.api.CreateInstance(conf.String(), keys, !gc.RuntimeConf().NoInstanceCreds) + instance, err := gc.flight.api.CreateInstance(conf.String(), keys, options.AdditionalDisks, !gc.RuntimeConf().NoInstanceCreds) if err != nil { return nil, err }