diff --git a/src/cmd/linuxkit/gcp.go b/src/cmd/linuxkit/gcp.go index 297803019..acf49a495 100644 --- a/src/cmd/linuxkit/gcp.go +++ b/src/cmd/linuxkit/gcp.go @@ -178,7 +178,7 @@ func (g GCPClient) DeleteImage(name string) error { } // CreateInstance creates and starts an instance on GCP -func (g GCPClient) CreateInstance(name, image, zone, machineType string, diskSize int, replace bool) error { +func (g GCPClient) CreateInstance(name, image, zone, machineType string, disks Disks, replace bool) error { if replace { if err := g.DeleteInstance(name, zone, true); err != nil { return err @@ -197,32 +197,47 @@ func (g GCPClient) CreateInstance(name, image, zone, machineType string, diskSiz sshKey := new(string) *sshKey = fmt.Sprintf("moby:%s moby", string(ssh.MarshalAuthorizedKey(k))) - diskName := name + "-systemdisk" - diskOp, err := g.compute.Disks.Insert(g.projectName, zone, &compute.Disk{Name: diskName, SizeGb: int64(diskSize)}).Do() - if err != nil { - return err + instanceDisks := []*compute.AttachedDisk{ + { + AutoDelete: true, + Boot: true, + InitializeParams: &compute.AttachedDiskInitializeParams{ + SourceImage: fmt.Sprintf("global/images/%s", image), + }, + }, } - if err := g.pollZoneOperationStatus(diskOp.Name, zone); err != nil { - return err + + for i, disk := range disks { + var diskName string + if disk.Path != "" { + diskName = disk.Path + } else { + diskName = fmt.Sprintf("%s-disk-%d", name, i) + } + var diskSizeGb int64 + if disk.Size == 0 { + diskSizeGb = int64(1) + } else { + diskSizeGb = int64(convertMBtoGB(disk.Size)) + } + diskOp, err := g.compute.Disks.Insert(g.projectName, zone, &compute.Disk{Name: diskName, SizeGb: diskSizeGb}).Do() + if err != nil { + return err + } + if err := g.pollZoneOperationStatus(diskOp.Name, zone); err != nil { + return err + } + instanceDisks = append(instanceDisks, &compute.AttachedDisk{ + AutoDelete: true, + Boot: false, + Source: fmt.Sprintf("zones/%s/disks/%s", zone, diskName), + }) } instanceObj := &compute.Instance{ MachineType: fmt.Sprintf("zones/%s/machineTypes/%s", zone, machineType), Name: name, - Disks: []*compute.AttachedDisk{ - { - AutoDelete: true, - Boot: true, - InitializeParams: &compute.AttachedDiskInitializeParams{ - SourceImage: fmt.Sprintf("global/images/%s", image), - }, - }, - { - AutoDelete: true, - Boot: false, - Source: fmt.Sprintf("zones/%s/disks/%s", zone, diskName), - }, - }, + Disks: instanceDisks, NetworkInterfaces: []*compute.NetworkInterface{ { Network: "global/networks/default", diff --git a/src/cmd/linuxkit/run_gcp.go b/src/cmd/linuxkit/run_gcp.go index 41db96589..563f4b24e 100644 --- a/src/cmd/linuxkit/run_gcp.go +++ b/src/cmd/linuxkit/run_gcp.go @@ -14,15 +14,14 @@ const ( defaultMachine = "g1-small" defaultDiskSize = 1 // Environment variables. Some are non-standard - zoneVar = "CLOUDSDK_COMPUTE_ZONE" - machineVar = "CLOUDSDK_COMPUTE_MACHINE" // non-standard - keysVar = "CLOUDSDK_COMPUTE_KEYS" // non-standard - projectVar = "CLOUDSDK_CORE_PROJECT" - bucketVar = "CLOUDSDK_IMAGE_BUCKET" // non-standard - familyVar = "CLOUDSDK_IMAGE_FAMILY" // non-standard - publicVar = "CLOUDSDK_IMAGE_PUBLIC" // non-standard - nameVar = "CLOUDSDK_IMAGE_NAME" // non-standard - diskSizeVar = "CLOUDSDK_DISK_SIZE" // non-standard + zoneVar = "CLOUDSDK_COMPUTE_ZONE" + machineVar = "CLOUDSDK_COMPUTE_MACHINE" // non-standard + keysVar = "CLOUDSDK_COMPUTE_KEYS" // non-standard + projectVar = "CLOUDSDK_CORE_PROJECT" + bucketVar = "CLOUDSDK_IMAGE_BUCKET" // non-standard + familyVar = "CLOUDSDK_IMAGE_FAMILY" // non-standard + publicVar = "CLOUDSDK_IMAGE_PUBLIC" // non-standard + nameVar = "CLOUDSDK_IMAGE_NAME" // non-standard ) // Process the run arguments and execute run @@ -41,7 +40,9 @@ func runGcp(args []string) { machineFlag := flags.String("machine", defaultMachine, "GCP Machine Type") keysFlag := flags.String("keys", "", "Path to Service Account JSON key file") projectFlag := flags.String("project", "", "GCP Project Name") - diskSizeFlag := flags.Int("disk-size", 0, "Size of system disk in GB") + var disks Disks + flags.Var(&disks, "disk", "Disk config, may be repeated. [file=]diskName[,size=1G]") + skipCleanup := flags.Bool("skip-cleanup", false, "Don't remove images or VMs") if err := flags.Parse(args); err != nil { @@ -60,14 +61,13 @@ func runGcp(args []string) { machine := getStringValue(machineVar, *machineFlag, defaultMachine) keys := getStringValue(keysVar, *keysFlag, "") project := getStringValue(projectVar, *projectFlag, "") - diskSize := getIntValue(diskSizeVar, *diskSizeFlag, defaultDiskSize) client, err := NewGCPClient(keys, project) if err != nil { log.Fatalf("Unable to connect to GCP") } - if err = client.CreateInstance(name, name, zone, machine, diskSize, true); err != nil { + if err = client.CreateInstance(name, name, zone, machine, disks, true); err != nil { log.Fatal(err) } diff --git a/src/cmd/linuxkit/util.go b/src/cmd/linuxkit/util.go index f7a8b1faf..93bd2ff75 100644 --- a/src/cmd/linuxkit/util.go +++ b/src/cmd/linuxkit/util.go @@ -135,6 +135,18 @@ func getDiskSizeMB(s string) (int, error) { return 1024 * i, nil } +func convertMBtoGB(i int) int { + if i < 1024 { + return 1 + } + + if i%1024 == 0 { + return i / 1024 + } + + return (i + (1024 - i%1024)) / 1024 +} + // DiskConfig is the config for a disk type DiskConfig struct { Path string