Update cloud providers

This commit is contained in:
Jan Safranek 2016-09-07 10:16:17 +02:00
parent a24e6a90bd
commit 9903b389b3
7 changed files with 59 additions and 2 deletions

View File

@ -1401,6 +1401,9 @@ func (d *awsDisk) deleteVolume() (bool, error) {
if awsError.Code() == "InvalidVolume.NotFound" { if awsError.Code() == "InvalidVolume.NotFound" {
return false, nil return false, nil
} }
if awsError.Code() == "VolumeInUse" {
return false, volume.NewDeletedVolumeInUseError(err.Error())
}
} }
return false, fmt.Errorf("error deleting EBS volumes: %v", err) return false, fmt.Errorf("error deleting EBS volumes: %v", err)
} }

View File

@ -40,6 +40,7 @@ import (
netsets "k8s.io/kubernetes/pkg/util/net/sets" netsets "k8s.io/kubernetes/pkg/util/net/sets"
"k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/sets"
"k8s.io/kubernetes/pkg/util/wait" "k8s.io/kubernetes/pkg/util/wait"
"k8s.io/kubernetes/pkg/volume"
"cloud.google.com/go/compute/metadata" "cloud.google.com/go/compute/metadata"
"github.com/golang/glog" "github.com/golang/glog"
@ -2459,7 +2460,7 @@ func (gce *GCECloud) CreateDisk(name string, diskType string, zone string, sizeG
return gce.waitForZoneOp(createOp, zone) return gce.waitForZoneOp(createOp, zone)
} }
func (gce *GCECloud) DeleteDisk(diskToDelete string) error { func (gce *GCECloud) doDeleteDisk(diskToDelete string) error {
disk, err := gce.getDiskByNameUnknownZone(diskToDelete) disk, err := gce.getDiskByNameUnknownZone(diskToDelete)
if err != nil { if err != nil {
return err return err
@ -2473,6 +2474,30 @@ func (gce *GCECloud) DeleteDisk(diskToDelete string) error {
return gce.waitForZoneOp(deleteOp, disk.Zone) return gce.waitForZoneOp(deleteOp, disk.Zone)
} }
func (gce *GCECloud) DeleteDisk(diskToDelete string) error {
err := gce.doDeleteDisk(diskToDelete)
if isGCEError(err, "resourceInUseByAnotherResource") {
return volume.NewDeletedVolumeInUseError(err.Error())
}
return err
}
// isGCEError returns true if given error is a googleapi.Error with given
// reason (e.g. "resourceInUseByAnotherResource")
func isGCEError(err error, reason string) bool {
apiErr, ok := err.(*googleapi.Error)
if !ok {
return false
}
for _, e := range apiErr.Errors {
if e.Reason == reason {
return true
}
}
return false
}
// Builds the labels that should be automatically added to a PersistentVolume backed by a GCE PD // Builds the labels that should be automatically added to a PersistentVolume backed by a GCE PD
// Specifically, this builds FailureDomain (zone) and Region labels. // Specifically, this builds FailureDomain (zone) and Region labels.
// The PersistentVolumeLabel admission controller calls this and adds the labels when a PV is created. // The PersistentVolumeLabel admission controller calls this and adds the labels when a PV is created.

View File

@ -23,6 +23,8 @@ import (
"path" "path"
"strings" "strings"
"k8s.io/kubernetes/pkg/volume"
"github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/openstack" "github.com/rackspace/gophercloud/openstack"
"github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes" "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes"
@ -182,6 +184,15 @@ func (os *OpenStack) GetDevicePath(diskId string) string {
} }
func (os *OpenStack) DeleteVolume(volumeName string) error { func (os *OpenStack) DeleteVolume(volumeName string) error {
used, err := os.diskIsUsed(volumeName)
if err != nil {
return err
}
if used {
msg := fmt.Sprintf("Cannot delete the volume %q, it's still attached to a node", volumeName)
return volume.NewDeletedVolumeInUseError(msg)
}
sClient, err := openstack.NewBlockStorageV1(os.provider, gophercloud.EndpointOpts{ sClient, err := openstack.NewBlockStorageV1(os.provider, gophercloud.EndpointOpts{
Region: os.region, Region: os.region,
}) })
@ -228,3 +239,15 @@ func (os *OpenStack) DiskIsAttached(diskName, instanceID string) (bool, error) {
} }
return false, nil return false, nil
} }
// diskIsUsed returns true a disk is attached to any node.
func (os *OpenStack) diskIsUsed(diskName string) (bool, error) {
disk, err := os.getVolume(diskName)
if err != nil {
return false, err
}
if len(disk.Attachments) > 0 {
return true, nil
}
return false, nil
}

View File

@ -77,7 +77,7 @@ func TestDeleteSync(t *testing.T) {
// delete failure - delete() returns error // delete failure - delete() returns error
"8-5 - delete returns error", "8-5 - delete returns error",
newVolumeArray("volume8-5", "1Gi", "uid8-5", "claim8-5", api.VolumeBound, api.PersistentVolumeReclaimDelete), newVolumeArray("volume8-5", "1Gi", "uid8-5", "claim8-5", api.VolumeBound, api.PersistentVolumeReclaimDelete),
withMessage("Delete of volume \"volume8-5\" failed: Mock delete error", newVolumeArray("volume8-5", "1Gi", "uid8-5", "claim8-5", api.VolumeFailed, api.PersistentVolumeReclaimDelete)), withMessage("Mock delete error", newVolumeArray("volume8-5", "1Gi", "uid8-5", "claim8-5", api.VolumeFailed, api.PersistentVolumeReclaimDelete)),
noclaims, noclaims,
noclaims, noclaims,
[]string{"Warning VolumeFailedDelete"}, noerrors, []string{"Warning VolumeFailedDelete"}, noerrors,

View File

@ -49,6 +49,8 @@ func (util *AWSDiskUtil) DeleteVolume(d *awsElasticBlockStoreDeleter) error {
deleted, err := cloud.DeleteDisk(d.volumeID) deleted, err := cloud.DeleteDisk(d.volumeID)
if err != nil { if err != nil {
// AWS cloud provider returns volume.deletedVolumeInUseError when
// necessary, no handling needed here.
glog.V(2).Infof("Error deleting EBS Disk volume %s: %v", d.volumeID, err) glog.V(2).Infof("Error deleting EBS Disk volume %s: %v", d.volumeID, err)
return err return err
} }

View File

@ -124,6 +124,8 @@ func (util *CinderDiskUtil) DeleteVolume(cd *cinderVolumeDeleter) error {
} }
if err = cloud.DeleteVolume(cd.pdName); err != nil { if err = cloud.DeleteVolume(cd.pdName); err != nil {
// OpenStack cloud provider returns volume.tryAgainError when necessary,
// no handling needed here.
glog.V(2).Infof("Error deleting cinder volume %s: %v", cd.pdName, err) glog.V(2).Infof("Error deleting cinder volume %s: %v", cd.pdName, err)
return err return err
} }

View File

@ -60,6 +60,8 @@ func (util *GCEDiskUtil) DeleteVolume(d *gcePersistentDiskDeleter) error {
if err = cloud.DeleteDisk(d.pdName); err != nil { if err = cloud.DeleteDisk(d.pdName); err != nil {
glog.V(2).Infof("Error deleting GCE PD volume %s: %v", d.pdName, err) glog.V(2).Infof("Error deleting GCE PD volume %s: %v", d.pdName, err)
// GCE cloud provider returns volume.deletedVolumeInUseError when
// necessary, no handling needed here.
return err return err
} }
glog.V(2).Infof("Successfully deleted GCE PD volume %s", d.pdName) glog.V(2).Infof("Successfully deleted GCE PD volume %s", d.pdName)