Commit a0fe767f authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #51539 from saad-ali/enableAlphaGCEDiskAPI

Automatic merge from submit-queue (batch tested with PRs 51439, 51361, 51140, 51539, 51585) Enable alpha GCE disk API This PR builds on top of #50467 to allow the GCE disk API to use either the alpha or stable APIs. CC @freehan
parents 99c5295f 4ca1dbc5
......@@ -131,16 +131,36 @@ type GCECloud struct {
type ServiceManager interface {
// Creates a new persistent disk on GCE with the given disk spec.
CreateDisk(project string, zone string, disk *compute.Disk) (*compute.Operation, error)
CreateDisk(
name string,
sizeGb int64,
tagsStr string,
diskTypeURI string,
zone string) (gceObject, error)
// Attach a persistent disk on GCE with the given disk spec to the specified instance.
AttachDisk(diskName string,
diskKind string,
diskZone string,
readWrite string,
source string,
diskType string,
instanceName string) (gceObject, error)
// Detach a persistent disk on GCE with the given disk spec from the specified instance.
DetachDisk(
instanceZone string,
instanceName string,
devicePath string) (gceObject, error)
// Gets the persistent disk from GCE with the given diskName.
GetDisk(project string, zone string, diskName string) (*compute.Disk, error)
GetDisk(project string, zone string, diskName string) (*GCEDisk, error)
// Deletes the persistent disk from GCE with the given diskName.
DeleteDisk(project string, zone string, disk string) (*compute.Operation, error)
DeleteDisk(project string, zone string, disk string) (gceObject, error)
// Waits until GCE reports the given operation in the given zone as done.
WaitForZoneOp(op *compute.Operation, zone string, mc *metricContext) error
WaitForZoneOp(op gceObject, zone string, mc *metricContext) error
}
type GCEServiceManager struct {
......@@ -717,29 +737,118 @@ func newOauthClient(tokenSource oauth2.TokenSource) (*http.Client, error) {
}
func (manager *GCEServiceManager) CreateDisk(
project string,
zone string,
disk *compute.Disk) (*compute.Operation, error) {
name string,
sizeGb int64,
tagsStr string,
diskTypeURI string,
zone string) (gceObject, error) {
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
diskToCreateAlpha := &computealpha.Disk{
Name: name,
SizeGb: sizeGb,
Description: tagsStr,
Type: diskTypeURI,
}
return manager.gce.serviceAlpha.Disks.Insert(manager.gce.projectID, zone, diskToCreateAlpha).Do()
}
diskToCreateV1 := &compute.Disk{
Name: name,
SizeGb: sizeGb,
Description: tagsStr,
Type: diskTypeURI,
}
return manager.gce.service.Disks.Insert(manager.gce.projectID, zone, diskToCreateV1).Do()
}
func (manager *GCEServiceManager) AttachDisk(
diskName string,
diskKind string,
diskZone string,
readWrite string,
source string,
diskType string,
instanceName string) (gceObject, error) {
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
attachedDiskAlpha := &computealpha.AttachedDisk{
DeviceName: diskName,
Kind: diskKind,
Mode: readWrite,
Source: source,
Type: diskType,
}
return manager.gce.serviceAlpha.Instances.AttachDisk(
manager.gce.projectID, diskZone, instanceName, attachedDiskAlpha).Do()
}
return manager.gce.service.Disks.Insert(project, zone, disk).Do()
attachedDiskV1 := &compute.AttachedDisk{
DeviceName: diskName,
Kind: diskKind,
Mode: readWrite,
Source: source,
Type: diskType,
}
return manager.gce.service.Instances.AttachDisk(
manager.gce.projectID, diskZone, instanceName, attachedDiskV1).Do()
}
func (manager *GCEServiceManager) DetachDisk(
instanceZone string,
instanceName string,
devicePath string) (gceObject, error) {
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
manager.gce.serviceAlpha.Instances.DetachDisk(
manager.gce.projectID, instanceZone, instanceName, devicePath).Do()
}
return manager.gce.service.Instances.DetachDisk(
manager.gce.projectID, instanceZone, instanceName, devicePath).Do()
}
func (manager *GCEServiceManager) GetDisk(
project string,
zone string,
diskName string) (*compute.Disk, error) {
diskName string) (*GCEDisk, error) {
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
diskAlpha, err := manager.gce.serviceAlpha.Disks.Get(project, zone, diskName).Do()
if err != nil {
return nil, err
}
return manager.gce.service.Disks.Get(project, zone, diskName).Do()
return &GCEDisk{
Zone: lastComponent(diskAlpha.Zone),
Name: diskAlpha.Name,
Kind: diskAlpha.Kind,
Type: diskAlpha.Type,
}, nil
}
diskStable, err := manager.gce.service.Disks.Get(project, zone, diskName).Do()
if err != nil {
return nil, err
}
return &GCEDisk{
Zone: lastComponent(diskStable.Zone),
Name: diskStable.Name,
Kind: diskStable.Kind,
Type: diskStable.Type,
}, nil
}
func (manager *GCEServiceManager) DeleteDisk(
project string,
zone string,
diskName string) (*compute.Operation, error) {
diskName string) (gceObject, error) {
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
return manager.gce.serviceAlpha.Disks.Delete(project, zone, diskName).Do()
}
return manager.gce.service.Disks.Delete(project, zone, diskName).Do()
}
func (manager *GCEServiceManager) WaitForZoneOp(op *compute.Operation, zone string, mc *metricContext) error {
func (manager *GCEServiceManager) WaitForZoneOp(op gceObject, zone string, mc *metricContext) error {
return manager.gce.waitForZoneOp(op, zone, mc)
}
......@@ -23,7 +23,13 @@ import (
)
// All known alpha features
var knownAlphaFeatures = map[string]bool{}
var knownAlphaFeatures = map[string]bool{
GCEDiskAlphaFeatureGate: true,
}
const (
GCEDiskAlphaFeatureGate = "GCEDiskAlphaAPI"
)
type AlphaFeatureGate struct {
features map[string]bool
......
......@@ -28,7 +28,6 @@ import (
"k8s.io/kubernetes/pkg/volume"
"github.com/golang/glog"
compute "google.golang.org/api/compute/v1"
"google.golang.org/api/googleapi"
)
......@@ -40,6 +39,7 @@ const (
diskTypeDefault = DiskTypeStandard
diskTypeUriTemplate = "%s/zones/%s/diskTypes/%s"
diskTypePersistent = "PERSISTENT"
)
// Disks is interface for manipulation with GCE PDs.
......@@ -101,17 +101,18 @@ func (gce *GCECloud) AttachDisk(diskName string, nodeName types.NodeName, readOn
if readOnly {
readWrite = "READ_ONLY"
}
attachedDisk := gce.convertDiskToAttachedDisk(disk, readWrite)
mc := newDiskMetricContext("attach", instance.Zone)
attachOp, err := gce.service.Instances.AttachDisk(
gce.projectID, disk.Zone, instance.Name, attachedDisk).Do()
source := gce.service.BasePath + strings.Join([]string{
gce.projectID, "zones", disk.Zone, "disks", disk.Name}, "/")
attachOp, err := gce.manager.AttachDisk(
disk.Name, disk.Kind, disk.Zone, readWrite, source, diskTypePersistent, instance.Name)
if err != nil {
return mc.Observe(err)
}
return gce.waitForZoneOp(attachOp, disk.Zone, mc)
return gce.manager.WaitForZoneOp(attachOp, disk.Zone, mc)
}
func (gce *GCECloud) DetachDisk(devicePath string, nodeName types.NodeName) error {
......@@ -131,12 +132,12 @@ func (gce *GCECloud) DetachDisk(devicePath string, nodeName types.NodeName) erro
}
mc := newDiskMetricContext("detach", inst.Zone)
detachOp, err := gce.service.Instances.DetachDisk(gce.projectID, inst.Zone, inst.Name, devicePath).Do()
detachOp, err := gce.manager.DetachDisk(inst.Zone, inst.Name, devicePath)
if err != nil {
return mc.Observe(err)
}
return gce.waitForZoneOp(detachOp, inst.Zone, mc)
return gce.manager.WaitForZoneOp(detachOp, inst.Zone, mc)
}
func (gce *GCECloud) DiskIsAttached(diskName string, nodeName types.NodeName) (bool, error) {
......@@ -236,15 +237,11 @@ func (gce *GCECloud) CreateDisk(
}
diskTypeUri := projectsApiEndpoint + fmt.Sprintf(diskTypeUriTemplate, gce.projectID, zone, diskType)
diskToCreate := &compute.Disk{
Name: name,
SizeGb: sizeGb,
Description: tagsStr,
Type: diskTypeUri,
}
mc := newDiskMetricContext("create", zone)
createOp, err := gce.manager.CreateDisk(gce.projectID, zone, diskToCreate)
createOp, err := gce.manager.CreateDisk(
name, sizeGb, tagsStr, diskTypeUri, zone)
if isGCEError(err, "alreadyExists") {
glog.Warningf("GCE PD %q already exists, reusing", name)
return nil
......@@ -325,13 +322,7 @@ func (gce *GCECloud) findDiskByName(diskName string, zone string) (*GCEDisk, err
mc := newDiskMetricContext("get", zone)
disk, err := gce.manager.GetDisk(gce.projectID, zone, diskName)
if err == nil {
d := &GCEDisk{
Zone: lastComponent(disk.Zone),
Name: disk.Name,
Kind: disk.Kind,
Type: disk.Type,
}
return d, mc.Observe(nil)
return disk, mc.Observe(nil)
}
if !isHTTPErrorCode(err, http.StatusNotFound) {
return nil, mc.Observe(err)
......@@ -418,18 +409,6 @@ func (gce *GCECloud) doDeleteDisk(diskToDelete string) error {
return gce.manager.WaitForZoneOp(deleteOp, disk.Zone, mc)
}
// Converts a Disk resource to an AttachedDisk resource.
func (gce *GCECloud) convertDiskToAttachedDisk(disk *GCEDisk, readWrite string) *compute.AttachedDisk {
return &compute.AttachedDisk{
DeviceName: disk.Name,
Kind: disk.Kind,
Mode: readWrite,
Source: gce.service.BasePath + strings.Join([]string{
gce.projectID, "zones", disk.Zone, "disks", disk.Name}, "/"),
Type: "PERSISTENT",
}
}
// isGCEError returns true if given error is a googleapi.Error with given
// reason (e.g. "resourceInUseByAnotherResource")
func isGCEError(err error, reason string) bool {
......
......@@ -78,6 +78,11 @@ func setupProviderConfig() error {
managedZones = []string{zone}
}
gceAlphaFeatureGate, err := gcecloud.NewAlphaFeatureGate([]string{})
if err != nil {
glog.Errorf("Encountered error for creating alpha feature gate: %v", err)
}
gceCloud, err := gcecloud.CreateGCECloud(&gcecloud.CloudConfig{
ApiEndpoint: framework.TestContext.CloudConfig.ApiEndpoint,
ProjectID: framework.TestContext.CloudConfig.ProjectID,
......@@ -89,7 +94,8 @@ func setupProviderConfig() error {
NodeTags: nil,
NodeInstancePrefix: "",
TokenSource: nil,
UseMetadataServer: false})
UseMetadataServer: false,
AlphaFeatureGate: gceAlphaFeatureGate})
if err != nil {
return fmt.Errorf("Error building GCE/GKE provider: %v", err)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment