mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-02 00:07:50 +00:00
Merge pull request #51281 from verult/GCEDiskCleanup
Automatic merge from submit-queue (batch tested with PRs 43016, 50503, 51281, 51518, 51582). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.. Refactor: Moving disk-related cloud provider operations to gce_disks.go **What this PR does / why we need it**: The main GCE cloud provider code (pkg/cloudprovider/providers/gce/gce.go) should not contain disk-related operations. Moved them to gce_disks.go **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes #51280 **Release note**: ```release-note NONE ``` /release-note-none /sig storage /assign @msau42 @bowei
This commit is contained in:
commit
55798b265c
@ -125,7 +125,7 @@ type GCECloud struct {
|
|||||||
nodeInstancePrefix string // If non-"", an advisory prefix for all nodes in the cluster
|
nodeInstancePrefix string // If non-"", an advisory prefix for all nodes in the cluster
|
||||||
useMetadataServer bool
|
useMetadataServer bool
|
||||||
operationPollRateLimiter flowcontrol.RateLimiter
|
operationPollRateLimiter flowcontrol.RateLimiter
|
||||||
manager ServiceManager
|
manager diskServiceManager
|
||||||
// sharedResourceLock is used to serialize GCE operations that may mutate shared state to
|
// sharedResourceLock is used to serialize GCE operations that may mutate shared state to
|
||||||
// prevent inconsistencies. For example, load balancers manipulation methods will take the
|
// prevent inconsistencies. For example, load balancers manipulation methods will take the
|
||||||
// lock to prevent shared resources from being prematurely deleted while the operation is
|
// lock to prevent shared resources from being prematurely deleted while the operation is
|
||||||
@ -138,59 +138,6 @@ type GCECloud struct {
|
|||||||
AlphaFeatureGate *AlphaFeatureGate
|
AlphaFeatureGate *AlphaFeatureGate
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServiceManager interface {
|
|
||||||
// Creates a new persistent disk on GCE with the given disk spec.
|
|
||||||
CreateDisk(
|
|
||||||
name string,
|
|
||||||
sizeGb int64,
|
|
||||||
tagsStr string,
|
|
||||||
diskType string,
|
|
||||||
zone string) (gceObject, error)
|
|
||||||
|
|
||||||
// Creates a new regional persistent disk on GCE with the given disk spec.
|
|
||||||
CreateRegionalDisk(
|
|
||||||
name string,
|
|
||||||
sizeGb int64,
|
|
||||||
tagsStr string,
|
|
||||||
diskType string,
|
|
||||||
zones sets.String) (gceObject, error)
|
|
||||||
|
|
||||||
// Deletes the persistent disk from GCE with the given diskName.
|
|
||||||
DeleteDisk(zone string, disk string) (gceObject, error)
|
|
||||||
|
|
||||||
// Deletes the regional persistent disk from GCE with the given diskName.
|
|
||||||
DeleteRegionalDisk(diskName string) (gceObject, error)
|
|
||||||
|
|
||||||
// Attach a persistent disk on GCE with the given disk spec to the specified instance.
|
|
||||||
AttachDisk(
|
|
||||||
disk *GCEDisk,
|
|
||||||
readWrite string,
|
|
||||||
instanceZone 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(zone string, diskName string) (*GCEDisk, error)
|
|
||||||
|
|
||||||
// Gets the regional persistent disk from GCE with the given diskName.
|
|
||||||
GetRegionalDisk(diskName string) (*GCEDisk, error)
|
|
||||||
|
|
||||||
// Waits until GCE reports the given operation in the given zone as done.
|
|
||||||
WaitForZoneOp(op gceObject, zone string, mc *metricContext) error
|
|
||||||
|
|
||||||
// Waits until GCE reports the given operation in the given region is done.
|
|
||||||
WaitForRegionalOp(op gceObject, mc *metricContext) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type GCEServiceManager struct {
|
|
||||||
gce *GCECloud
|
|
||||||
}
|
|
||||||
|
|
||||||
type ConfigGlobal struct {
|
type ConfigGlobal struct {
|
||||||
TokenURL string `gcfg:"token-url"`
|
TokenURL string `gcfg:"token-url"`
|
||||||
TokenBody string `gcfg:"token-body"`
|
TokenBody string `gcfg:"token-body"`
|
||||||
@ -511,7 +458,7 @@ func CreateGCECloud(config *CloudConfig) (*GCECloud, error) {
|
|||||||
AlphaFeatureGate: config.AlphaFeatureGate,
|
AlphaFeatureGate: config.AlphaFeatureGate,
|
||||||
}
|
}
|
||||||
|
|
||||||
gce.manager = &GCEServiceManager{gce}
|
gce.manager = &gceServiceManager{gce}
|
||||||
|
|
||||||
// Registering the KMS plugin only the first time.
|
// Registering the KMS plugin only the first time.
|
||||||
kmsPluginRegisterOnce.Do(func() {
|
kmsPluginRegisterOnce.Do(func() {
|
||||||
@ -768,335 +715,7 @@ func newOauthClient(tokenSource oauth2.TokenSource) (*http.Client, error) {
|
|||||||
return oauth2.NewClient(oauth2.NoContext, tokenSource), nil
|
return oauth2.NewClient(oauth2.NoContext, tokenSource), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *GCEServiceManager) CreateDisk(
|
func (manager *gceServiceManager) getProjectsAPIEndpoint() string {
|
||||||
name string,
|
|
||||||
sizeGb int64,
|
|
||||||
tagsStr string,
|
|
||||||
diskType string,
|
|
||||||
zone string) (gceObject, error) {
|
|
||||||
diskTypeURI, err := manager.getDiskTypeURI(
|
|
||||||
manager.gce.region /* diskRegion */, singleZone{zone}, diskType)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
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) CreateRegionalDisk(
|
|
||||||
name string,
|
|
||||||
sizeGb int64,
|
|
||||||
tagsStr string,
|
|
||||||
diskType string,
|
|
||||||
replicaZones sets.String) (gceObject, error) {
|
|
||||||
diskTypeURI, err := manager.getDiskTypeURI(
|
|
||||||
manager.gce.region /* diskRegion */, multiZone{replicaZones}, diskType)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
fullyQualifiedReplicaZones := []string{}
|
|
||||||
for _, replicaZone := range replicaZones.UnsortedList() {
|
|
||||||
fullyQualifiedReplicaZones = append(
|
|
||||||
fullyQualifiedReplicaZones, manager.getReplicaZoneURI(replicaZone))
|
|
||||||
}
|
|
||||||
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
|
|
||||||
diskToCreateAlpha := &computealpha.Disk{
|
|
||||||
Name: name,
|
|
||||||
SizeGb: sizeGb,
|
|
||||||
Description: tagsStr,
|
|
||||||
Type: diskTypeURI,
|
|
||||||
ReplicaZones: fullyQualifiedReplicaZones,
|
|
||||||
}
|
|
||||||
return manager.gce.serviceAlpha.RegionDisks.Insert(
|
|
||||||
manager.gce.projectID, manager.gce.region, diskToCreateAlpha).Do()
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("The regional PD feature is only available via the GCE Alpha API. Enable \"GCEDiskAlphaAPI\" in the list of \"alpha-features\" in \"gce.conf\" to use the feature.")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (manager *GCEServiceManager) AttachDisk(
|
|
||||||
disk *GCEDisk,
|
|
||||||
readWrite string,
|
|
||||||
instanceZone string,
|
|
||||||
instanceName string) (gceObject, error) {
|
|
||||||
source, err := manager.getDiskSourceURI(disk)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
|
|
||||||
attachedDiskAlpha := &computealpha.AttachedDisk{
|
|
||||||
DeviceName: disk.Name,
|
|
||||||
Kind: disk.Kind,
|
|
||||||
Mode: readWrite,
|
|
||||||
Source: source,
|
|
||||||
Type: diskTypePersistent,
|
|
||||||
}
|
|
||||||
return manager.gce.serviceAlpha.Instances.AttachDisk(
|
|
||||||
manager.gce.projectID, instanceZone, instanceName, attachedDiskAlpha).Do()
|
|
||||||
}
|
|
||||||
|
|
||||||
attachedDiskV1 := &compute.AttachedDisk{
|
|
||||||
DeviceName: disk.Name,
|
|
||||||
Kind: disk.Kind,
|
|
||||||
Mode: readWrite,
|
|
||||||
Source: source,
|
|
||||||
Type: disk.Type,
|
|
||||||
}
|
|
||||||
return manager.gce.service.Instances.AttachDisk(
|
|
||||||
manager.gce.projectID, instanceZone, 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(
|
|
||||||
zone string,
|
|
||||||
diskName string) (*GCEDisk, error) {
|
|
||||||
if zone == "" {
|
|
||||||
return nil, fmt.Errorf("Can not fetch disk %q. Zone is empty.", diskName)
|
|
||||||
}
|
|
||||||
|
|
||||||
if diskName == "" {
|
|
||||||
return nil, fmt.Errorf("Can not fetch disk. Zone is specified (%q). But disk name is empty.", zone)
|
|
||||||
}
|
|
||||||
|
|
||||||
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
|
|
||||||
diskAlpha, err := manager.gce.serviceAlpha.Disks.Get(
|
|
||||||
manager.gce.projectID, zone, diskName).Do()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var zoneInfo zoneType
|
|
||||||
if len(diskAlpha.ReplicaZones) > 1 {
|
|
||||||
zones := sets.NewString()
|
|
||||||
for _, zoneURI := range diskAlpha.ReplicaZones {
|
|
||||||
zones.Insert(lastComponent(zoneURI))
|
|
||||||
}
|
|
||||||
zoneInfo = multiZone{zones}
|
|
||||||
} else {
|
|
||||||
zoneInfo = singleZone{lastComponent(diskAlpha.Zone)}
|
|
||||||
if diskAlpha.Zone == "" {
|
|
||||||
zoneInfo = singleZone{lastComponent(zone)}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
region := strings.TrimSpace(lastComponent(diskAlpha.Region))
|
|
||||||
if region == "" {
|
|
||||||
region, err = manager.getRegionFromZone(zoneInfo)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to extract region from zone for %q/%q err=%v", zone, diskName, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &GCEDisk{
|
|
||||||
ZoneInfo: zoneInfo,
|
|
||||||
Region: region,
|
|
||||||
Name: diskAlpha.Name,
|
|
||||||
Kind: diskAlpha.Kind,
|
|
||||||
Type: diskAlpha.Type,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
diskStable, err := manager.gce.service.Disks.Get(
|
|
||||||
manager.gce.projectID, zone, diskName).Do()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
zoneInfo := singleZone{strings.TrimSpace(lastComponent(diskStable.Zone))}
|
|
||||||
if zoneInfo.zone == "" {
|
|
||||||
zoneInfo = singleZone{zone}
|
|
||||||
}
|
|
||||||
|
|
||||||
region, err := manager.getRegionFromZone(zoneInfo)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to extract region from zone for %q/%q err=%v", zone, diskName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &GCEDisk{
|
|
||||||
ZoneInfo: zoneInfo,
|
|
||||||
Region: region,
|
|
||||||
Name: diskStable.Name,
|
|
||||||
Kind: diskStable.Kind,
|
|
||||||
Type: diskStable.Type,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (manager *GCEServiceManager) GetRegionalDisk(
|
|
||||||
diskName string) (*GCEDisk, error) {
|
|
||||||
|
|
||||||
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
|
|
||||||
diskAlpha, err := manager.gce.serviceAlpha.RegionDisks.Get(
|
|
||||||
manager.gce.projectID, manager.gce.region, diskName).Do()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
zones := sets.NewString()
|
|
||||||
for _, zoneURI := range diskAlpha.ReplicaZones {
|
|
||||||
zones.Insert(lastComponent(zoneURI))
|
|
||||||
}
|
|
||||||
|
|
||||||
return &GCEDisk{
|
|
||||||
ZoneInfo: multiZone{zones},
|
|
||||||
Region: lastComponent(diskAlpha.Region),
|
|
||||||
Name: diskAlpha.Name,
|
|
||||||
Kind: diskAlpha.Kind,
|
|
||||||
Type: diskAlpha.Type,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("The regional PD feature is only available via the GCE Alpha API. Enable \"GCEDiskAlphaAPI\" in the list of \"alpha-features\" in \"gce.conf\" to use the feature.")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (manager *GCEServiceManager) DeleteDisk(
|
|
||||||
zone string,
|
|
||||||
diskName string) (gceObject, error) {
|
|
||||||
|
|
||||||
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
|
|
||||||
return manager.gce.serviceAlpha.Disks.Delete(
|
|
||||||
manager.gce.projectID, zone, diskName).Do()
|
|
||||||
}
|
|
||||||
|
|
||||||
return manager.gce.service.Disks.Delete(
|
|
||||||
manager.gce.projectID, zone, diskName).Do()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (manager *GCEServiceManager) DeleteRegionalDisk(
|
|
||||||
diskName string) (gceObject, error) {
|
|
||||||
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
|
|
||||||
return manager.gce.serviceAlpha.RegionDisks.Delete(
|
|
||||||
manager.gce.projectID, manager.gce.region, diskName).Do()
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("DeleteRegionalDisk is a regional PD feature and is only available via the GCE Alpha API. Enable \"GCEDiskAlphaAPI\" in the list of \"alpha-features\" in \"gce.conf\" to use the feature.")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (manager *GCEServiceManager) WaitForZoneOp(
|
|
||||||
op gceObject, zone string, mc *metricContext) error {
|
|
||||||
return manager.gce.waitForZoneOp(op, zone, mc)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (manager *GCEServiceManager) WaitForRegionalOp(
|
|
||||||
op gceObject, mc *metricContext) error {
|
|
||||||
return manager.gce.waitForRegionOp(op, manager.gce.region, mc)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (manager *GCEServiceManager) getDiskSourceURI(disk *GCEDisk) (string, error) {
|
|
||||||
getProjectsAPIEndpoint := manager.getProjectsAPIEndpoint()
|
|
||||||
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
|
|
||||||
getProjectsAPIEndpoint = manager.getProjectsAPIEndpointAlpha()
|
|
||||||
}
|
|
||||||
|
|
||||||
switch zoneInfo := disk.ZoneInfo.(type) {
|
|
||||||
case singleZone:
|
|
||||||
if zoneInfo.zone == "" || disk.Region == "" {
|
|
||||||
// Unexpected, but sanity-check
|
|
||||||
return "", fmt.Errorf("PD does not have zone/region information: %#v", disk)
|
|
||||||
}
|
|
||||||
|
|
||||||
return getProjectsAPIEndpoint + fmt.Sprintf(
|
|
||||||
diskSourceURITemplateSingleZone,
|
|
||||||
manager.gce.projectID,
|
|
||||||
zoneInfo.zone,
|
|
||||||
disk.Name), nil
|
|
||||||
case multiZone:
|
|
||||||
if zoneInfo.replicaZones == nil || zoneInfo.replicaZones.Len() <= 0 {
|
|
||||||
// Unexpected, but sanity-check
|
|
||||||
return "", fmt.Errorf("PD is regional but does not have any replicaZones specified: %v", disk)
|
|
||||||
}
|
|
||||||
return getProjectsAPIEndpoint + fmt.Sprintf(
|
|
||||||
diskSourceURITemplateRegional,
|
|
||||||
manager.gce.projectID,
|
|
||||||
disk.Region,
|
|
||||||
disk.Name), nil
|
|
||||||
case nil:
|
|
||||||
// Unexpected, but sanity-check
|
|
||||||
return "", fmt.Errorf("PD did not have ZoneInfo: %v", disk)
|
|
||||||
default:
|
|
||||||
// Unexpected, but sanity-check
|
|
||||||
return "", fmt.Errorf("disk.ZoneInfo has unexpected type %T", zoneInfo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (manager *GCEServiceManager) getDiskTypeURI(
|
|
||||||
diskRegion string, diskZoneInfo zoneType, diskType string) (string, error) {
|
|
||||||
getProjectsAPIEndpoint := manager.getProjectsAPIEndpoint()
|
|
||||||
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
|
|
||||||
getProjectsAPIEndpoint = manager.getProjectsAPIEndpointAlpha()
|
|
||||||
}
|
|
||||||
|
|
||||||
switch zoneInfo := diskZoneInfo.(type) {
|
|
||||||
case singleZone:
|
|
||||||
if zoneInfo.zone == "" {
|
|
||||||
return "", fmt.Errorf("zone is empty: %v", zoneInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
return getProjectsAPIEndpoint + fmt.Sprintf(
|
|
||||||
diskTypeURITemplateSingleZone,
|
|
||||||
manager.gce.projectID,
|
|
||||||
zoneInfo.zone,
|
|
||||||
diskType), nil
|
|
||||||
case multiZone:
|
|
||||||
if zoneInfo.replicaZones == nil || zoneInfo.replicaZones.Len() <= 0 {
|
|
||||||
return "", fmt.Errorf("zoneInfo is regional but does not have any replicaZones specified: %v", zoneInfo)
|
|
||||||
}
|
|
||||||
return getProjectsAPIEndpoint + fmt.Sprintf(
|
|
||||||
diskTypeURITemplateRegional,
|
|
||||||
manager.gce.projectID,
|
|
||||||
diskRegion,
|
|
||||||
diskType), nil
|
|
||||||
case nil:
|
|
||||||
return "", fmt.Errorf("zoneInfo nil")
|
|
||||||
default:
|
|
||||||
return "", fmt.Errorf("zoneInfo has unexpected type %T", zoneInfo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (manager *GCEServiceManager) getReplicaZoneURI(zone string) string {
|
|
||||||
getProjectsAPIEndpoint := manager.getProjectsAPIEndpoint()
|
|
||||||
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
|
|
||||||
getProjectsAPIEndpoint = manager.getProjectsAPIEndpointAlpha()
|
|
||||||
}
|
|
||||||
|
|
||||||
return getProjectsAPIEndpoint + fmt.Sprintf(
|
|
||||||
replicaZoneURITemplateSingleZone,
|
|
||||||
manager.gce.projectID,
|
|
||||||
zone)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (manager *GCEServiceManager) getProjectsAPIEndpoint() string {
|
|
||||||
projectsApiEndpoint := gceComputeAPIEndpoint + "projects/"
|
projectsApiEndpoint := gceComputeAPIEndpoint + "projects/"
|
||||||
if manager.gce.service != nil {
|
if manager.gce.service != nil {
|
||||||
projectsApiEndpoint = manager.gce.service.BasePath
|
projectsApiEndpoint = manager.gce.service.BasePath
|
||||||
@ -1105,7 +724,7 @@ func (manager *GCEServiceManager) getProjectsAPIEndpoint() string {
|
|||||||
return projectsApiEndpoint
|
return projectsApiEndpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *GCEServiceManager) getProjectsAPIEndpointAlpha() string {
|
func (manager *gceServiceManager) getProjectsAPIEndpointAlpha() string {
|
||||||
projectsApiEndpoint := gceComputeAPIEndpointAlpha + "projects/"
|
projectsApiEndpoint := gceComputeAPIEndpointAlpha + "projects/"
|
||||||
if manager.gce.service != nil {
|
if manager.gce.service != nil {
|
||||||
projectsApiEndpoint = manager.gce.serviceAlpha.BasePath
|
projectsApiEndpoint = manager.gce.serviceAlpha.BasePath
|
||||||
@ -1113,37 +732,3 @@ func (manager *GCEServiceManager) getProjectsAPIEndpointAlpha() string {
|
|||||||
|
|
||||||
return projectsApiEndpoint
|
return projectsApiEndpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *GCEServiceManager) getRegionFromZone(zoneInfo zoneType) (string, error) {
|
|
||||||
var zone string
|
|
||||||
switch zoneInfo := zoneInfo.(type) {
|
|
||||||
case singleZone:
|
|
||||||
if zoneInfo.zone == "" {
|
|
||||||
// Unexpected, but sanity-check
|
|
||||||
return "", fmt.Errorf("PD is single zone, but zone is not specified: %#v", zoneInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
zone = zoneInfo.zone
|
|
||||||
case multiZone:
|
|
||||||
if zoneInfo.replicaZones == nil || zoneInfo.replicaZones.Len() <= 0 {
|
|
||||||
// Unexpected, but sanity-check
|
|
||||||
return "", fmt.Errorf("PD is regional but does not have any replicaZones specified: %v", zoneInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
zone = zoneInfo.replicaZones.UnsortedList()[0]
|
|
||||||
case nil:
|
|
||||||
// Unexpected, but sanity-check
|
|
||||||
return "", fmt.Errorf("zoneInfo is nil")
|
|
||||||
default:
|
|
||||||
// Unexpected, but sanity-check
|
|
||||||
return "", fmt.Errorf("zoneInfo has unexpected type %T", zoneInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
region, err := GetGCERegion(zone)
|
|
||||||
if err != nil {
|
|
||||||
glog.Warningf("failed to parse GCE region from zone %q: %v", zone, err)
|
|
||||||
region = manager.gce.region
|
|
||||||
}
|
|
||||||
|
|
||||||
return region, nil
|
|
||||||
}
|
|
||||||
|
@ -32,6 +32,8 @@ import (
|
|||||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||||
|
compute "google.golang.org/api/compute/v1"
|
||||||
"google.golang.org/api/googleapi"
|
"google.golang.org/api/googleapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -52,6 +54,421 @@ const (
|
|||||||
replicaZoneURITemplateSingleZone = "%s/zones/%s" // {gce.projectID}/zones/{disk.Zone}
|
replicaZoneURITemplateSingleZone = "%s/zones/%s" // {gce.projectID}/zones/{disk.Zone}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type diskServiceManager interface {
|
||||||
|
// Creates a new persistent disk on GCE with the given disk spec.
|
||||||
|
CreateDiskOnCloudProvider(
|
||||||
|
name string,
|
||||||
|
sizeGb int64,
|
||||||
|
tagsStr string,
|
||||||
|
diskType string,
|
||||||
|
zone string) (gceObject, error)
|
||||||
|
|
||||||
|
// Creates a new regional persistent disk on GCE with the given disk spec.
|
||||||
|
CreateRegionalDiskOnCloudProvider(
|
||||||
|
name string,
|
||||||
|
sizeGb int64,
|
||||||
|
tagsStr string,
|
||||||
|
diskType string,
|
||||||
|
zones sets.String) (gceObject, error)
|
||||||
|
|
||||||
|
// Deletes the persistent disk from GCE with the given diskName.
|
||||||
|
DeleteDiskOnCloudProvider(zone string, disk string) (gceObject, error)
|
||||||
|
|
||||||
|
// Deletes the regional persistent disk from GCE with the given diskName.
|
||||||
|
DeleteRegionalDiskOnCloudProvider(diskName string) (gceObject, error)
|
||||||
|
|
||||||
|
// Attach a persistent disk on GCE with the given disk spec to the specified instance.
|
||||||
|
AttachDiskOnCloudProvider(
|
||||||
|
disk *GCEDisk,
|
||||||
|
readWrite string,
|
||||||
|
instanceZone string,
|
||||||
|
instanceName string) (gceObject, error)
|
||||||
|
|
||||||
|
// Detach a persistent disk on GCE with the given disk spec from the specified instance.
|
||||||
|
DetachDiskOnCloudProvider(
|
||||||
|
instanceZone string,
|
||||||
|
instanceName string,
|
||||||
|
devicePath string) (gceObject, error)
|
||||||
|
|
||||||
|
// Gets the persistent disk from GCE with the given diskName.
|
||||||
|
GetDiskFromCloudProvider(zone string, diskName string) (*GCEDisk, error)
|
||||||
|
|
||||||
|
// Gets the regional persistent disk from GCE with the given diskName.
|
||||||
|
GetRegionalDiskFromCloudProvider(diskName string) (*GCEDisk, error)
|
||||||
|
|
||||||
|
// Waits until GCE reports the given operation in the given zone as done.
|
||||||
|
WaitForZoneOp(op gceObject, zone string, mc *metricContext) error
|
||||||
|
|
||||||
|
// Waits until GCE reports the given operation in the given region is done.
|
||||||
|
WaitForRegionalOp(op gceObject, mc *metricContext) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type gceServiceManager struct {
|
||||||
|
gce *GCECloud
|
||||||
|
}
|
||||||
|
|
||||||
|
func (manager *gceServiceManager) CreateDiskOnCloudProvider(
|
||||||
|
name string,
|
||||||
|
sizeGb int64,
|
||||||
|
tagsStr string,
|
||||||
|
diskType string,
|
||||||
|
zone string) (gceObject, error) {
|
||||||
|
diskTypeURI, err := manager.getDiskTypeURI(
|
||||||
|
manager.gce.region /* diskRegion */, singleZone{zone}, diskType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
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) CreateRegionalDiskOnCloudProvider(
|
||||||
|
name string,
|
||||||
|
sizeGb int64,
|
||||||
|
tagsStr string,
|
||||||
|
diskType string,
|
||||||
|
replicaZones sets.String) (gceObject, error) {
|
||||||
|
diskTypeURI, err := manager.getDiskTypeURI(
|
||||||
|
manager.gce.region /* diskRegion */, multiZone{replicaZones}, diskType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fullyQualifiedReplicaZones := []string{}
|
||||||
|
for _, replicaZone := range replicaZones.UnsortedList() {
|
||||||
|
fullyQualifiedReplicaZones = append(
|
||||||
|
fullyQualifiedReplicaZones, manager.getReplicaZoneURI(replicaZone))
|
||||||
|
}
|
||||||
|
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
|
||||||
|
diskToCreateAlpha := &computealpha.Disk{
|
||||||
|
Name: name,
|
||||||
|
SizeGb: sizeGb,
|
||||||
|
Description: tagsStr,
|
||||||
|
Type: diskTypeURI,
|
||||||
|
ReplicaZones: fullyQualifiedReplicaZones,
|
||||||
|
}
|
||||||
|
return manager.gce.serviceAlpha.RegionDisks.Insert(
|
||||||
|
manager.gce.projectID, manager.gce.region, diskToCreateAlpha).Do()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("The regional PD feature is only available via the GCE Alpha API. Enable \"GCEDiskAlphaAPI\" in the list of \"alpha-features\" in \"gce.conf\" to use the feature.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (manager *gceServiceManager) AttachDiskOnCloudProvider(
|
||||||
|
disk *GCEDisk,
|
||||||
|
readWrite string,
|
||||||
|
instanceZone string,
|
||||||
|
instanceName string) (gceObject, error) {
|
||||||
|
source, err := manager.getDiskSourceURI(disk)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
|
||||||
|
attachedDiskAlpha := &computealpha.AttachedDisk{
|
||||||
|
DeviceName: disk.Name,
|
||||||
|
Kind: disk.Kind,
|
||||||
|
Mode: readWrite,
|
||||||
|
Source: source,
|
||||||
|
Type: diskTypePersistent,
|
||||||
|
}
|
||||||
|
return manager.gce.serviceAlpha.Instances.AttachDisk(
|
||||||
|
manager.gce.projectID, instanceZone, instanceName, attachedDiskAlpha).Do()
|
||||||
|
}
|
||||||
|
|
||||||
|
attachedDiskV1 := &compute.AttachedDisk{
|
||||||
|
DeviceName: disk.Name,
|
||||||
|
Kind: disk.Kind,
|
||||||
|
Mode: readWrite,
|
||||||
|
Source: source,
|
||||||
|
Type: disk.Type,
|
||||||
|
}
|
||||||
|
return manager.gce.service.Instances.AttachDisk(
|
||||||
|
manager.gce.projectID, instanceZone, instanceName, attachedDiskV1).Do()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (manager *gceServiceManager) DetachDiskOnCloudProvider(
|
||||||
|
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) GetDiskFromCloudProvider(
|
||||||
|
zone string,
|
||||||
|
diskName string) (*GCEDisk, error) {
|
||||||
|
if zone == "" {
|
||||||
|
return nil, fmt.Errorf("Can not fetch disk %q. Zone is empty.", diskName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if diskName == "" {
|
||||||
|
return nil, fmt.Errorf("Can not fetch disk. Zone is specified (%q). But disk name is empty.", zone)
|
||||||
|
}
|
||||||
|
|
||||||
|
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
|
||||||
|
diskAlpha, err := manager.gce.serviceAlpha.Disks.Get(
|
||||||
|
manager.gce.projectID, zone, diskName).Do()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var zoneInfo zoneType
|
||||||
|
if len(diskAlpha.ReplicaZones) > 1 {
|
||||||
|
zones := sets.NewString()
|
||||||
|
for _, zoneURI := range diskAlpha.ReplicaZones {
|
||||||
|
zones.Insert(lastComponent(zoneURI))
|
||||||
|
}
|
||||||
|
zoneInfo = multiZone{zones}
|
||||||
|
} else {
|
||||||
|
zoneInfo = singleZone{lastComponent(diskAlpha.Zone)}
|
||||||
|
if diskAlpha.Zone == "" {
|
||||||
|
zoneInfo = singleZone{lastComponent(zone)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
region := strings.TrimSpace(lastComponent(diskAlpha.Region))
|
||||||
|
if region == "" {
|
||||||
|
region, err = manager.getRegionFromZone(zoneInfo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to extract region from zone for %q/%q err=%v", zone, diskName, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &GCEDisk{
|
||||||
|
ZoneInfo: zoneInfo,
|
||||||
|
Region: region,
|
||||||
|
Name: diskAlpha.Name,
|
||||||
|
Kind: diskAlpha.Kind,
|
||||||
|
Type: diskAlpha.Type,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
diskStable, err := manager.gce.service.Disks.Get(
|
||||||
|
manager.gce.projectID, zone, diskName).Do()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
zoneInfo := singleZone{strings.TrimSpace(lastComponent(diskStable.Zone))}
|
||||||
|
if zoneInfo.zone == "" {
|
||||||
|
zoneInfo = singleZone{zone}
|
||||||
|
}
|
||||||
|
|
||||||
|
region, err := manager.getRegionFromZone(zoneInfo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to extract region from zone for %q/%q err=%v", zone, diskName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &GCEDisk{
|
||||||
|
ZoneInfo: zoneInfo,
|
||||||
|
Region: region,
|
||||||
|
Name: diskStable.Name,
|
||||||
|
Kind: diskStable.Kind,
|
||||||
|
Type: diskStable.Type,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (manager *gceServiceManager) GetRegionalDiskFromCloudProvider(
|
||||||
|
diskName string) (*GCEDisk, error) {
|
||||||
|
|
||||||
|
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
|
||||||
|
diskAlpha, err := manager.gce.serviceAlpha.RegionDisks.Get(
|
||||||
|
manager.gce.projectID, manager.gce.region, diskName).Do()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
zones := sets.NewString()
|
||||||
|
for _, zoneURI := range diskAlpha.ReplicaZones {
|
||||||
|
zones.Insert(lastComponent(zoneURI))
|
||||||
|
}
|
||||||
|
|
||||||
|
return &GCEDisk{
|
||||||
|
ZoneInfo: multiZone{zones},
|
||||||
|
Region: lastComponent(diskAlpha.Region),
|
||||||
|
Name: diskAlpha.Name,
|
||||||
|
Kind: diskAlpha.Kind,
|
||||||
|
Type: diskAlpha.Type,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("The regional PD feature is only available via the GCE Alpha API. Enable \"GCEDiskAlphaAPI\" in the list of \"alpha-features\" in \"gce.conf\" to use the feature.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (manager *gceServiceManager) DeleteDiskOnCloudProvider(
|
||||||
|
zone string,
|
||||||
|
diskName string) (gceObject, error) {
|
||||||
|
|
||||||
|
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
|
||||||
|
return manager.gce.serviceAlpha.Disks.Delete(
|
||||||
|
manager.gce.projectID, zone, diskName).Do()
|
||||||
|
}
|
||||||
|
|
||||||
|
return manager.gce.service.Disks.Delete(
|
||||||
|
manager.gce.projectID, zone, diskName).Do()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (manager *gceServiceManager) DeleteRegionalDiskOnCloudProvider(
|
||||||
|
diskName string) (gceObject, error) {
|
||||||
|
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
|
||||||
|
return manager.gce.serviceAlpha.RegionDisks.Delete(
|
||||||
|
manager.gce.projectID, manager.gce.region, diskName).Do()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("DeleteRegionalDiskOnCloudProvider is a regional PD feature and is only available via the GCE Alpha API. Enable \"GCEDiskAlphaAPI\" in the list of \"alpha-features\" in \"gce.conf\" to use the feature.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (manager *gceServiceManager) WaitForZoneOp(
|
||||||
|
op gceObject, zone string, mc *metricContext) error {
|
||||||
|
return manager.gce.waitForZoneOp(op, zone, mc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (manager *gceServiceManager) WaitForRegionalOp(
|
||||||
|
op gceObject, mc *metricContext) error {
|
||||||
|
return manager.gce.waitForRegionOp(op, manager.gce.region, mc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (manager *gceServiceManager) getDiskSourceURI(disk *GCEDisk) (string, error) {
|
||||||
|
getProjectsAPIEndpoint := manager.getProjectsAPIEndpoint()
|
||||||
|
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
|
||||||
|
getProjectsAPIEndpoint = manager.getProjectsAPIEndpointAlpha()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch zoneInfo := disk.ZoneInfo.(type) {
|
||||||
|
case singleZone:
|
||||||
|
if zoneInfo.zone == "" || disk.Region == "" {
|
||||||
|
// Unexpected, but sanity-check
|
||||||
|
return "", fmt.Errorf("PD does not have zone/region information: %#v", disk)
|
||||||
|
}
|
||||||
|
|
||||||
|
return getProjectsAPIEndpoint + fmt.Sprintf(
|
||||||
|
diskSourceURITemplateSingleZone,
|
||||||
|
manager.gce.projectID,
|
||||||
|
zoneInfo.zone,
|
||||||
|
disk.Name), nil
|
||||||
|
case multiZone:
|
||||||
|
if zoneInfo.replicaZones == nil || zoneInfo.replicaZones.Len() <= 0 {
|
||||||
|
// Unexpected, but sanity-check
|
||||||
|
return "", fmt.Errorf("PD is regional but does not have any replicaZones specified: %v", disk)
|
||||||
|
}
|
||||||
|
return getProjectsAPIEndpoint + fmt.Sprintf(
|
||||||
|
diskSourceURITemplateRegional,
|
||||||
|
manager.gce.projectID,
|
||||||
|
disk.Region,
|
||||||
|
disk.Name), nil
|
||||||
|
case nil:
|
||||||
|
// Unexpected, but sanity-check
|
||||||
|
return "", fmt.Errorf("PD did not have ZoneInfo: %v", disk)
|
||||||
|
default:
|
||||||
|
// Unexpected, but sanity-check
|
||||||
|
return "", fmt.Errorf("disk.ZoneInfo has unexpected type %T", zoneInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (manager *gceServiceManager) getDiskTypeURI(
|
||||||
|
diskRegion string, diskZoneInfo zoneType, diskType string) (string, error) {
|
||||||
|
getProjectsAPIEndpoint := manager.getProjectsAPIEndpoint()
|
||||||
|
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
|
||||||
|
getProjectsAPIEndpoint = manager.getProjectsAPIEndpointAlpha()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch zoneInfo := diskZoneInfo.(type) {
|
||||||
|
case singleZone:
|
||||||
|
if zoneInfo.zone == "" {
|
||||||
|
return "", fmt.Errorf("zone is empty: %v", zoneInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
return getProjectsAPIEndpoint + fmt.Sprintf(
|
||||||
|
diskTypeURITemplateSingleZone,
|
||||||
|
manager.gce.projectID,
|
||||||
|
zoneInfo.zone,
|
||||||
|
diskType), nil
|
||||||
|
case multiZone:
|
||||||
|
if zoneInfo.replicaZones == nil || zoneInfo.replicaZones.Len() <= 0 {
|
||||||
|
return "", fmt.Errorf("zoneInfo is regional but does not have any replicaZones specified: %v", zoneInfo)
|
||||||
|
}
|
||||||
|
return getProjectsAPIEndpoint + fmt.Sprintf(
|
||||||
|
diskTypeURITemplateRegional,
|
||||||
|
manager.gce.projectID,
|
||||||
|
diskRegion,
|
||||||
|
diskType), nil
|
||||||
|
case nil:
|
||||||
|
return "", fmt.Errorf("zoneInfo nil")
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf("zoneInfo has unexpected type %T", zoneInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (manager *gceServiceManager) getReplicaZoneURI(zone string) string {
|
||||||
|
getProjectsAPIEndpoint := manager.getProjectsAPIEndpoint()
|
||||||
|
if manager.gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
|
||||||
|
getProjectsAPIEndpoint = manager.getProjectsAPIEndpointAlpha()
|
||||||
|
}
|
||||||
|
|
||||||
|
return getProjectsAPIEndpoint + fmt.Sprintf(
|
||||||
|
replicaZoneURITemplateSingleZone,
|
||||||
|
manager.gce.projectID,
|
||||||
|
zone)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (manager *gceServiceManager) getRegionFromZone(zoneInfo zoneType) (string, error) {
|
||||||
|
var zone string
|
||||||
|
switch zoneInfo := zoneInfo.(type) {
|
||||||
|
case singleZone:
|
||||||
|
if zoneInfo.zone == "" {
|
||||||
|
// Unexpected, but sanity-check
|
||||||
|
return "", fmt.Errorf("PD is single zone, but zone is not specified: %#v", zoneInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
zone = zoneInfo.zone
|
||||||
|
case multiZone:
|
||||||
|
if zoneInfo.replicaZones == nil || zoneInfo.replicaZones.Len() <= 0 {
|
||||||
|
// Unexpected, but sanity-check
|
||||||
|
return "", fmt.Errorf("PD is regional but does not have any replicaZones specified: %v", zoneInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
zone = zoneInfo.replicaZones.UnsortedList()[0]
|
||||||
|
case nil:
|
||||||
|
// Unexpected, but sanity-check
|
||||||
|
return "", fmt.Errorf("zoneInfo is nil")
|
||||||
|
default:
|
||||||
|
// Unexpected, but sanity-check
|
||||||
|
return "", fmt.Errorf("zoneInfo has unexpected type %T", zoneInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
region, err := GetGCERegion(zone)
|
||||||
|
if err != nil {
|
||||||
|
glog.Warningf("failed to parse GCE region from zone %q: %v", zone, err)
|
||||||
|
region = manager.gce.region
|
||||||
|
}
|
||||||
|
|
||||||
|
return region, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Disks is interface for manipulation with GCE PDs.
|
// Disks is interface for manipulation with GCE PDs.
|
||||||
type Disks interface {
|
type Disks interface {
|
||||||
// AttachDisk attaches given disk to the node with the specified NodeName.
|
// AttachDisk attaches given disk to the node with the specified NodeName.
|
||||||
@ -175,7 +592,7 @@ func (gce *GCECloud) AttachDisk(diskName string, nodeName types.NodeName, readOn
|
|||||||
readWrite = "READ_ONLY"
|
readWrite = "READ_ONLY"
|
||||||
}
|
}
|
||||||
|
|
||||||
attachOp, err := gce.manager.AttachDisk(
|
attachOp, err := gce.manager.AttachDiskOnCloudProvider(
|
||||||
disk, readWrite, instance.Zone, instance.Name)
|
disk, readWrite, instance.Zone, instance.Name)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -202,7 +619,7 @@ func (gce *GCECloud) DetachDisk(devicePath string, nodeName types.NodeName) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
mc := newDiskMetricContextZonal("detach", gce.region, inst.Zone)
|
mc := newDiskMetricContextZonal("detach", gce.region, inst.Zone)
|
||||||
detachOp, err := gce.manager.DetachDisk(inst.Zone, inst.Name, devicePath)
|
detachOp, err := gce.manager.DetachDiskOnCloudProvider(inst.Zone, inst.Name, devicePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mc.Observe(err)
|
return mc.Observe(err)
|
||||||
}
|
}
|
||||||
@ -292,7 +709,7 @@ func (gce *GCECloud) CreateDisk(
|
|||||||
|
|
||||||
mc := newDiskMetricContextZonal("create", gce.region, zone)
|
mc := newDiskMetricContextZonal("create", gce.region, zone)
|
||||||
|
|
||||||
createOp, err := gce.manager.CreateDisk(
|
createOp, err := gce.manager.CreateDiskOnCloudProvider(
|
||||||
name, sizeGb, tagsStr, diskType, zone)
|
name, sizeGb, tagsStr, diskType, zone)
|
||||||
|
|
||||||
if isGCEError(err, "alreadyExists") {
|
if isGCEError(err, "alreadyExists") {
|
||||||
@ -341,7 +758,7 @@ func (gce *GCECloud) CreateRegionalDisk(
|
|||||||
|
|
||||||
mc := newDiskMetricContextRegional("create", gce.region)
|
mc := newDiskMetricContextRegional("create", gce.region)
|
||||||
|
|
||||||
createOp, err := gce.manager.CreateRegionalDisk(
|
createOp, err := gce.manager.CreateRegionalDiskOnCloudProvider(
|
||||||
name, sizeGb, tagsStr, diskType, replicaZones)
|
name, sizeGb, tagsStr, diskType, replicaZones)
|
||||||
|
|
||||||
if isGCEError(err, "alreadyExists") {
|
if isGCEError(err, "alreadyExists") {
|
||||||
@ -469,7 +886,7 @@ func (gce *GCECloud) GetAutoLabelsForPD(name string, zone string) (map[string]st
|
|||||||
// If not found, returns (nil, nil)
|
// If not found, returns (nil, nil)
|
||||||
func (gce *GCECloud) findDiskByName(diskName string, zone string) (*GCEDisk, error) {
|
func (gce *GCECloud) findDiskByName(diskName string, zone string) (*GCEDisk, error) {
|
||||||
mc := newDiskMetricContextZonal("get", gce.region, zone)
|
mc := newDiskMetricContextZonal("get", gce.region, zone)
|
||||||
disk, err := gce.manager.GetDisk(zone, diskName)
|
disk, err := gce.manager.GetDiskFromCloudProvider(zone, diskName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return disk, mc.Observe(nil)
|
return disk, mc.Observe(nil)
|
||||||
}
|
}
|
||||||
@ -492,7 +909,7 @@ func (gce *GCECloud) getDiskByName(diskName string, zone string) (*GCEDisk, erro
|
|||||||
// If not found, returns (nil, nil)
|
// If not found, returns (nil, nil)
|
||||||
func (gce *GCECloud) findRegionalDiskByName(diskName string) (*GCEDisk, error) {
|
func (gce *GCECloud) findRegionalDiskByName(diskName string) (*GCEDisk, error) {
|
||||||
mc := newDiskMetricContextRegional("get", gce.region)
|
mc := newDiskMetricContextRegional("get", gce.region)
|
||||||
disk, err := gce.manager.GetRegionalDisk(diskName)
|
disk, err := gce.manager.GetRegionalDiskFromCloudProvider(diskName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return disk, mc.Observe(nil)
|
return disk, mc.Observe(nil)
|
||||||
}
|
}
|
||||||
@ -593,14 +1010,14 @@ func (gce *GCECloud) doDeleteDisk(diskToDelete string) error {
|
|||||||
switch zoneInfo := disk.ZoneInfo.(type) {
|
switch zoneInfo := disk.ZoneInfo.(type) {
|
||||||
case singleZone:
|
case singleZone:
|
||||||
mc = newDiskMetricContextZonal("delete", disk.Region, zoneInfo.zone)
|
mc = newDiskMetricContextZonal("delete", disk.Region, zoneInfo.zone)
|
||||||
deleteOp, err := gce.manager.DeleteDisk(zoneInfo.zone, disk.Name)
|
deleteOp, err := gce.manager.DeleteDiskOnCloudProvider(zoneInfo.zone, disk.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mc.Observe(err)
|
return mc.Observe(err)
|
||||||
}
|
}
|
||||||
return gce.manager.WaitForZoneOp(deleteOp, zoneInfo.zone, mc)
|
return gce.manager.WaitForZoneOp(deleteOp, zoneInfo.zone, mc)
|
||||||
case multiZone:
|
case multiZone:
|
||||||
mc = newDiskMetricContextRegional("delete", disk.Region)
|
mc = newDiskMetricContextRegional("delete", disk.Region)
|
||||||
deleteOp, err := gce.manager.DeleteRegionalDisk(disk.Name)
|
deleteOp, err := gce.manager.DeleteRegionalDiskOnCloudProvider(disk.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mc.Observe(err)
|
return mc.Observe(err)
|
||||||
}
|
}
|
||||||
|
@ -386,8 +386,8 @@ func TestDeleteDisk_SameDiskMultiZone(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Act */
|
/* Act */
|
||||||
// DeleteDisk will call FakeServiceManager.GetDisk() with all zones,
|
// DeleteDisk will call FakeServiceManager.GetDiskFromCloudProvider() with all zones,
|
||||||
// and FakeServiceManager.GetDisk() always returns a disk,
|
// and FakeServiceManager.GetDiskFromCloudProvider() always returns a disk,
|
||||||
// so DeleteDisk thinks a disk with diskName exists in all zones.
|
// so DeleteDisk thinks a disk with diskName exists in all zones.
|
||||||
err := gce.DeleteDisk(diskName)
|
err := gce.DeleteDisk(diskName)
|
||||||
|
|
||||||
@ -662,7 +662,7 @@ func newFakeManager(gceProjectID string, gceRegion string) *FakeServiceManager {
|
|||||||
* Upon disk creation, disk info is stored in FakeServiceManager
|
* Upon disk creation, disk info is stored in FakeServiceManager
|
||||||
* to be used by other tested methods.
|
* to be used by other tested methods.
|
||||||
*/
|
*/
|
||||||
func (manager *FakeServiceManager) CreateDisk(
|
func (manager *FakeServiceManager) CreateDiskOnCloudProvider(
|
||||||
name string,
|
name string,
|
||||||
sizeGb int64,
|
sizeGb int64,
|
||||||
tagsStr string,
|
tagsStr string,
|
||||||
@ -716,7 +716,7 @@ func (manager *FakeServiceManager) CreateDisk(
|
|||||||
* Upon disk creation, disk info is stored in FakeServiceManager
|
* Upon disk creation, disk info is stored in FakeServiceManager
|
||||||
* to be used by other tested methods.
|
* to be used by other tested methods.
|
||||||
*/
|
*/
|
||||||
func (manager *FakeServiceManager) CreateRegionalDisk(
|
func (manager *FakeServiceManager) CreateRegionalDiskOnCloudProvider(
|
||||||
name string,
|
name string,
|
||||||
sizeGb int64,
|
sizeGb int64,
|
||||||
tagsStr string,
|
tagsStr string,
|
||||||
@ -746,7 +746,7 @@ func (manager *FakeServiceManager) CreateRegionalDisk(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *FakeServiceManager) AttachDisk(
|
func (manager *FakeServiceManager) AttachDiskOnCloudProvider(
|
||||||
disk *GCEDisk,
|
disk *GCEDisk,
|
||||||
readWrite string,
|
readWrite string,
|
||||||
instanceZone string,
|
instanceZone string,
|
||||||
@ -767,7 +767,7 @@ func (manager *FakeServiceManager) AttachDisk(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *FakeServiceManager) DetachDisk(
|
func (manager *FakeServiceManager) DetachDiskOnCloudProvider(
|
||||||
instanceZone string,
|
instanceZone string,
|
||||||
instanceName string,
|
instanceName string,
|
||||||
devicePath string) (gceObject, error) {
|
devicePath string) (gceObject, error) {
|
||||||
@ -789,7 +789,7 @@ func (manager *FakeServiceManager) DetachDisk(
|
|||||||
/**
|
/**
|
||||||
* Gets disk info stored in the FakeServiceManager.
|
* Gets disk info stored in the FakeServiceManager.
|
||||||
*/
|
*/
|
||||||
func (manager *FakeServiceManager) GetDisk(
|
func (manager *FakeServiceManager) GetDiskFromCloudProvider(
|
||||||
zone string, diskName string) (*GCEDisk, error) {
|
zone string, diskName string) (*GCEDisk, error) {
|
||||||
|
|
||||||
if manager.zonalDisks[zone] == "" {
|
if manager.zonalDisks[zone] == "" {
|
||||||
@ -814,7 +814,7 @@ func (manager *FakeServiceManager) GetDisk(
|
|||||||
/**
|
/**
|
||||||
* Gets disk info stored in the FakeServiceManager.
|
* Gets disk info stored in the FakeServiceManager.
|
||||||
*/
|
*/
|
||||||
func (manager *FakeServiceManager) GetRegionalDisk(
|
func (manager *FakeServiceManager) GetRegionalDiskFromCloudProvider(
|
||||||
diskName string) (*GCEDisk, error) {
|
diskName string) (*GCEDisk, error) {
|
||||||
|
|
||||||
if _, ok := manager.regionalDisks[diskName]; !ok {
|
if _, ok := manager.regionalDisks[diskName]; !ok {
|
||||||
@ -839,7 +839,7 @@ func (manager *FakeServiceManager) GetRegionalDisk(
|
|||||||
/**
|
/**
|
||||||
* Disk info is removed from the FakeServiceManager.
|
* Disk info is removed from the FakeServiceManager.
|
||||||
*/
|
*/
|
||||||
func (manager *FakeServiceManager) DeleteDisk(
|
func (manager *FakeServiceManager) DeleteDiskOnCloudProvider(
|
||||||
zone string,
|
zone string,
|
||||||
disk string) (gceObject, error) {
|
disk string) (gceObject, error) {
|
||||||
|
|
||||||
@ -861,7 +861,7 @@ func (manager *FakeServiceManager) DeleteDisk(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *FakeServiceManager) DeleteRegionalDisk(
|
func (manager *FakeServiceManager) DeleteRegionalDiskOnCloudProvider(
|
||||||
disk string) (gceObject, error) {
|
disk string) (gceObject, error) {
|
||||||
|
|
||||||
manager.deleteDiskCalled = true
|
manager.deleteDiskCalled = true
|
||||||
|
Loading…
Reference in New Issue
Block a user