mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-19 09:16:29 +00:00
Merge pull request #3790 from giggsoff/support-gcp-vtpm
Support for vTPM on GCP
This commit is contained in:
commit
1073b2dd8d
@ -8,6 +8,7 @@ import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/term"
|
||||
@ -20,8 +21,13 @@ import (
|
||||
"google.golang.org/api/storage/v1"
|
||||
)
|
||||
|
||||
const pollingInterval = 500 * time.Millisecond
|
||||
const timeout = 300
|
||||
const (
|
||||
pollingInterval = 500 * time.Millisecond
|
||||
timeout = 300
|
||||
|
||||
uefiCompatibleFeature = "UEFI_COMPATIBLE"
|
||||
vmxImageLicence = "projects/vm-options/global/licenses/enable-vmx"
|
||||
)
|
||||
|
||||
// GCPClient contains state required for communication with GCP
|
||||
type GCPClient struct {
|
||||
@ -125,8 +131,8 @@ func (g GCPClient) UploadFile(src, dst, bucketName string, public bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateImage creates a GCP image using the a source from Google Storage
|
||||
func (g GCPClient) CreateImage(name, storageURL, family string, nested, replace bool) error {
|
||||
// CreateImage creates a GCP image using the source from Google Storage
|
||||
func (g GCPClient) CreateImage(name, storageURL, family string, nested, uefi, replace bool) error {
|
||||
if replace {
|
||||
if err := g.DeleteImage(name); err != nil {
|
||||
return err
|
||||
@ -146,7 +152,13 @@ func (g GCPClient) CreateImage(name, storageURL, family string, nested, replace
|
||||
}
|
||||
|
||||
if nested {
|
||||
imgObj.Licenses = []string{"projects/vm-options/global/licenses/enable-vmx"}
|
||||
imgObj.Licenses = []string{vmxImageLicence}
|
||||
}
|
||||
|
||||
if uefi {
|
||||
imgObj.GuestOsFeatures = []*compute.GuestOsFeature{
|
||||
{Type: uefiCompatibleFeature},
|
||||
}
|
||||
}
|
||||
|
||||
op, err := g.compute.Images.Insert(g.projectName, imgObj).Do()
|
||||
@ -185,7 +197,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, disks Disks, data *string, nested, replace bool) error {
|
||||
func (g GCPClient) CreateInstance(name, image, zone, machineType string, disks Disks, data *string, nested, vtpm, replace bool) error {
|
||||
if replace {
|
||||
if err := g.DeleteInstance(name, zone, true); err != nil {
|
||||
return err
|
||||
@ -204,6 +216,34 @@ func (g GCPClient) CreateInstance(name, image, zone, machineType string, disks D
|
||||
sshKey := new(string)
|
||||
*sshKey = fmt.Sprintf("moby:%s moby", string(ssh.MarshalAuthorizedKey(k)))
|
||||
|
||||
// check provided image to be compatible with provided options
|
||||
op, err := g.compute.Images.Get(g.projectName, image).Do()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
uefiCompatible := false
|
||||
for _, feature := range op.GuestOsFeatures {
|
||||
if feature != nil && feature.Type == uefiCompatibleFeature {
|
||||
uefiCompatible = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if vtpm && !uefiCompatible {
|
||||
return fmt.Errorf("cannot use vTPM without UEFI_COMPATIBLE image")
|
||||
}
|
||||
// we should check for nested
|
||||
vmxLicense := false
|
||||
for _, license := range op.Licenses {
|
||||
// we omit hostname and version when define license
|
||||
if strings.HasSuffix(license, vmxImageLicence) {
|
||||
vmxLicense = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if nested && !vmxLicense {
|
||||
return fmt.Errorf("cannot use nested virtualization without enable-vmx image")
|
||||
}
|
||||
|
||||
instanceDisks := []*compute.AttachedDisk{
|
||||
{
|
||||
AutoDelete: true,
|
||||
@ -227,7 +267,13 @@ func (g GCPClient) CreateInstance(name, image, zone, machineType string, disks D
|
||||
} else {
|
||||
diskSizeGb = int64(convertMBtoGB(disk.Size))
|
||||
}
|
||||
diskOp, err := g.compute.Disks.Insert(g.projectName, zone, &compute.Disk{Name: diskName, SizeGb: diskSizeGb}).Do()
|
||||
diskObj := &compute.Disk{Name: diskName, SizeGb: diskSizeGb}
|
||||
if vtpm {
|
||||
diskObj.GuestOsFeatures = []*compute.GuestOsFeature{
|
||||
{Type: uefiCompatibleFeature},
|
||||
}
|
||||
}
|
||||
diskOp, err := g.compute.Disks.Insert(g.projectName, zone, diskObj).Do()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -274,9 +320,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"
|
||||
}
|
||||
if vtpm {
|
||||
instanceObj.ShieldedInstanceConfig = &compute.ShieldedInstanceConfig{EnableVtpm: true}
|
||||
}
|
||||
|
||||
// Don't wait for operation to complete!
|
||||
// A headstart is needed as by the time we've polled for this event to be
|
||||
|
@ -26,6 +26,7 @@ func pushGcp(args []string) {
|
||||
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")
|
||||
nestedVirt := flags.Bool("nested-virt", false, "Enabled nested virtualization for the image")
|
||||
uefiCompatible := flags.Bool("uefi-compatible", false, "Enable UEFI_COMPATIBLE feature for the image, required to enable vTPM.")
|
||||
|
||||
if err := flags.Parse(args); err != nil {
|
||||
log.Fatal("Unable to parse args")
|
||||
@ -65,7 +66,7 @@ func pushGcp(args []string) {
|
||||
if err != nil {
|
||||
log.Fatalf("Error copying to Google Storage: %v", err)
|
||||
}
|
||||
err = client.CreateImage(name, "https://storage.googleapis.com/"+bucket+"/"+name+suffix, family, *nestedVirt, true)
|
||||
err = client.CreateImage(name, "https://storage.googleapis.com/"+bucket+"/"+name+suffix, family, *nestedVirt, *uefiCompatible, true)
|
||||
if err != nil {
|
||||
log.Fatalf("Error creating Google Compute Image: %v", err)
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ func runGcp(args []string) {
|
||||
|
||||
skipCleanup := flags.Bool("skip-cleanup", false, "Don't remove images or VMs")
|
||||
nestedVirt := flags.Bool("nested-virt", false, "Enabled nested virtualization")
|
||||
vTPM := flags.Bool("vtpm", false, "Enable vTPM device")
|
||||
|
||||
data := flags.String("data", "", "String of metadata to pass to VM; error to specify both -data and -data-file")
|
||||
dataPath := flags.String("data-file", "", "Path to file containing metadata to pass to VM; error to specify both -data and -data-file")
|
||||
@ -87,7 +88,7 @@ func runGcp(args []string) {
|
||||
log.Fatalf("Unable to connect to GCP: %v", err)
|
||||
}
|
||||
|
||||
if err = client.CreateInstance(*name, image, zone, machine, disks, data, *nestedVirt, true); err != nil {
|
||||
if err = client.CreateInstance(*name, image, zone, machine, disks, data, *nestedVirt, *vTPM, true); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user