Skip to content

Commit 4b63246

Browse files
authored
Merge pull request #71 from lpabon/b66-v2.0
Persistent name and Exponential backoff
2 parents 4d23391 + 80dc4f6 commit 4b63246

File tree

2 files changed

+53
-8
lines changed

2 files changed

+53
-8
lines changed

cmd/csi-provisioner/csi-provisioner.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ var (
4242
kubeconfig = flag.String("kubeconfig", "", "Absolute path to the kubeconfig file. Either this or master needs to be set if the provisioner is being run out of cluster.")
4343
csiEndpoint = flag.String("csi-address", "/run/csi/socket", "The gRPC endpoint for Target CSI Volume")
4444
connectionTimeout = flag.Duration("connection-timeout", 10*time.Second, "Timeout for waiting for CSI driver socket.")
45-
volumeNamePrefix = flag.String("volume-name-prefix", "kubernetes-dynamic-pv", "Prefix to apply to the name of a created volume")
45+
volumeNamePrefix = flag.String("volume-name-prefix", "pvc", "Prefix to apply to the name of a created volume")
4646
volumeNameUUIDLength = flag.Int("volume-name-uuid-length", 16, "Length in characters for the generated uuid of a created volume")
4747

4848
provisionController *controller.ProvisionController

pkg/controller/controller.go

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,27 @@ import (
2929

3030
"k8s.io/api/core/v1"
3131
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
32-
"k8s.io/apimachinery/pkg/util/uuid"
32+
"k8s.io/apimachinery/pkg/util/wait"
3333
"k8s.io/client-go/kubernetes"
3434
"k8s.io/client-go/rest"
3535

3636
"google.golang.org/grpc"
37+
"google.golang.org/grpc/codes"
3738
"google.golang.org/grpc/connectivity"
39+
"google.golang.org/grpc/status"
3840

3941
"github.com/container-storage-interface/spec/lib/go/csi/v0"
4042
)
4143

4244
const (
4345
secretNameKey = "csiProvisionerSecretName"
4446
secretNamespaceKey = "csiProvisionerSecretNamespace"
47+
// Defines parameters for ExponentialBackoff used for executing
48+
// CSI CreateVolume API call, it gives approx 4 minutes for the CSI
49+
// driver to complete a volume creation.
50+
backoffDuration = time.Second * 5
51+
backoffFactor = 1.2
52+
backoffSteps = 10
4553
)
4654

4755
// CSIProvisioner struct
@@ -238,6 +246,18 @@ func checkDriverState(grpcClient *grpc.ClientConn, timeout time.Duration) (strin
238246
return driverName, nil
239247
}
240248

249+
func makeVolumeName(prefix, pvcUID string) (string, error) {
250+
// create persistent name based on a volumeNamePrefix and volumeNameUUIDLength
251+
// of PVC's UID
252+
if len(prefix) == 0 {
253+
return "", fmt.Errorf("Volume name prefix cannot be of length 0")
254+
}
255+
if len(pvcUID) == 0 {
256+
return "", fmt.Errorf("corrupted PVC object, it is missing UID")
257+
}
258+
return fmt.Sprintf("%s-%s", prefix, pvcUID), nil
259+
}
260+
241261
func (p *csiProvisioner) Provision(options controller.VolumeOptions) (*v1.PersistentVolume, error) {
242262
if options.PVC.Spec.Selector != nil {
243263
return nil, fmt.Errorf("claim Selector is not supported")
@@ -247,12 +267,16 @@ func (p *csiProvisioner) Provision(options controller.VolumeOptions) (*v1.Persis
247267
if err != nil {
248268
return nil, err
249269
}
250-
// create random share name
251-
share := fmt.Sprintf("%s-%s", p.volumeNamePrefix, strings.Replace(string(uuid.NewUUID()), "-", "", -1)[0:p.volumeNameUUIDLength])
270+
271+
share, err := makeVolumeName(p.volumeNamePrefix, fmt.Sprintf("%s", options.PVC.ObjectMeta.UID))
272+
if err != nil {
273+
return nil, err
274+
}
275+
252276
capacity := options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)]
253277
volSizeBytes := capacity.Value()
254278

255-
// Create a CSI CreateVolumeRequest
279+
// Create a CSI CreateVolumeRequest and Response
256280
req := csi.CreateVolumeRequest{
257281

258282
Name: share,
@@ -268,6 +292,8 @@ func (p *csiProvisioner) Provision(options controller.VolumeOptions) (*v1.Persis
268292
LimitBytes: int64(volSizeBytes),
269293
},
270294
}
295+
rep := &csi.CreateVolumeResponse{}
296+
271297
secret := v1.SecretReference{}
272298
if options.Parameters != nil {
273299
credentials, err := getCredentialsFromParameters(p.client, options.Parameters)
@@ -277,13 +303,32 @@ func (p *csiProvisioner) Provision(options controller.VolumeOptions) (*v1.Persis
277303
req.ControllerCreateSecrets = credentials
278304
secret.Name, secret.Namespace, _ = getSecretAndNamespaceFromParameters(options.Parameters)
279305
}
280-
ctx, cancel := context.WithTimeout(context.Background(), p.timeout)
281-
defer cancel()
282306

283-
rep, err := p.csiClient.CreateVolume(ctx, &req)
307+
opts := wait.Backoff{Duration: backoffDuration, Factor: backoffFactor, Steps: backoffSteps}
308+
err = wait.ExponentialBackoff(opts, func() (bool, error) {
309+
ctx, cancel := context.WithTimeout(context.Background(), p.timeout)
310+
defer cancel()
311+
rep, err = p.csiClient.CreateVolume(ctx, &req)
312+
if err == nil {
313+
// CreateVolume has finished successfully
314+
return true, nil
315+
}
316+
317+
if status, ok := status.FromError(err); ok {
318+
if status.Code() == codes.DeadlineExceeded {
319+
// CreateVolume timed out, give it another chance to complete
320+
glog.Warningf("CreateVolume timeout: %s has expired, operation will be retried", p.timeout.String())
321+
return false, nil
322+
}
323+
}
324+
// CreateVolume failed , no reason to retry, bailing from ExponentialBackoff
325+
return false, err
326+
})
327+
284328
if err != nil {
285329
return nil, err
286330
}
331+
287332
if rep.Volume != nil {
288333
glog.V(3).Infof("create volume rep: %+v", *rep.Volume)
289334
}

0 commit comments

Comments
 (0)