cmd/gcp: Add -nest-virt option to push and run

If the flag is set on push, then the image will have the license
set to enabled the currently experimental netsted virtualisation
feature. The flag currently also needs to be set on run to make
sure the right CPU model (at least Haswell) is selected.

Signed-off-by: Rolf Neugebauer <rolf.neugebauer@docker.com>
This commit is contained in:
Rolf Neugebauer 2018-01-17 14:07:27 +00:00
parent 358a020b1a
commit 0470dc89a8
3 changed files with 15 additions and 4 deletions

View File

@ -123,7 +123,7 @@ func (g GCPClient) UploadFile(src, dst, bucketName string, public bool) error {
} }
// CreateImage creates a GCP image using the a source from Google Storage // CreateImage creates a GCP image using the a source from Google Storage
func (g GCPClient) CreateImage(name, storageURL, family string, replace bool) error { func (g GCPClient) CreateImage(name, storageURL, family string, nested, replace bool) error {
if replace { if replace {
if err := g.DeleteImage(name); err != nil { if err := g.DeleteImage(name); err != nil {
return err return err
@ -142,6 +142,10 @@ func (g GCPClient) CreateImage(name, storageURL, family string, replace bool) er
imgObj.Family = family imgObj.Family = family
} }
if nested {
imgObj.Licenses = []string{"projects/vm-options/global/licenses/enable-vmx"}
}
op, err := g.compute.Images.Insert(g.projectName, imgObj).Do() op, err := g.compute.Images.Insert(g.projectName, imgObj).Do()
if err != nil { if err != nil {
return err return err
@ -178,7 +182,7 @@ func (g GCPClient) DeleteImage(name string) error {
} }
// CreateInstance creates and starts an instance on GCP // CreateInstance creates and starts an instance on GCP
func (g GCPClient) CreateInstance(name, image, zone, machineType string, disks Disks, replace bool) error { func (g GCPClient) CreateInstance(name, image, zone, machineType string, disks Disks, nested, replace bool) error {
if replace { if replace {
if err := g.DeleteInstance(name, zone, true); err != nil { if err := g.DeleteInstance(name, zone, true); err != nil {
return err return err
@ -262,6 +266,11 @@ func (g GCPClient) CreateInstance(name, image, zone, machineType string, disks D
}, },
} }
if nested {
// TODO(rn): We could/should check here if the image has nested virt enabled
instanceObj.MinCpuPlatform = "Intel Haswell"
}
// Don't wait for operation to complete! // Don't wait for operation to complete!
// A headstart is needed as by the time we've polled for this event to be // A headstart is needed as by the time we've polled for this event to be
// completed, the instance may have already terminated // completed, the instance may have already terminated

View File

@ -25,6 +25,7 @@ func pushGcp(args []string) {
publicFlag := flags.Bool("public", false, "Select if file on GCS should be public. *Optional*") publicFlag := flags.Bool("public", false, "Select if file on GCS should be public. *Optional*")
familyFlag := flags.String("family", "", "GCP Image Family. A group of images where the family name points to the most recent image. *Optional*") familyFlag := flags.String("family", "", "GCP Image Family. A group of images where the family name points to the most recent image. *Optional*")
nameFlag := flags.String("img-name", "", "Overrides the name used to identify the file in Google Storage and the VM image. Defaults to the base of 'path' with the '.img.tar.gz' suffix removed") nameFlag := flags.String("img-name", "", "Overrides the name used to identify the file in Google Storage and the VM image. Defaults to the base of 'path' with the '.img.tar.gz' suffix removed")
nestedVirt := flags.Bool("nested-virt", false, "Enabled nested virtualization for the image")
if err := flags.Parse(args); err != nil { if err := flags.Parse(args); err != nil {
log.Fatal("Unable to parse args") log.Fatal("Unable to parse args")
@ -64,7 +65,7 @@ func pushGcp(args []string) {
if err != nil { if err != nil {
log.Fatalf("Error copying to Google Storage: %v", err) log.Fatalf("Error copying to Google Storage: %v", err)
} }
err = client.CreateImage(name, "https://storage.googleapis.com/"+bucket+"/"+name+suffix, family, true) err = client.CreateImage(name, "https://storage.googleapis.com/"+bucket+"/"+name+suffix, family, *nestedVirt, true)
if err != nil { if err != nil {
log.Fatalf("Error creating Google Compute Image: %v", err) log.Fatalf("Error creating Google Compute Image: %v", err)
} }

View File

@ -43,6 +43,7 @@ func runGcp(args []string) {
flags.Var(&disks, "disk", "Disk config, may be repeated. [file=]diskName[,size=1G]") 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") skipCleanup := flags.Bool("skip-cleanup", false, "Don't remove images or VMs")
nestedVirt := flags.Bool("nested-virt", false, "Enabled nested virtualization")
if err := flags.Parse(args); err != nil { if err := flags.Parse(args); err != nil {
log.Fatal("Unable to parse args") log.Fatal("Unable to parse args")
@ -66,7 +67,7 @@ func runGcp(args []string) {
log.Fatalf("Unable to connect to GCP") log.Fatalf("Unable to connect to GCP")
} }
if err = client.CreateInstance(name, name, zone, machine, disks, true); err != nil { if err = client.CreateInstance(name, name, zone, machine, disks, *nestedVirt, true); err != nil {
log.Fatal(err) log.Fatal(err)
} }