Skip to content

Commit 20363a4

Browse files
einfachnuralexMichaelEischer
authored andcommitted
increased backoff for attach/detach
add exponential backoff for volume readiness (RPC: CreateVolume) (#7) Signed-off-by: Niclas Schad <[email protected]>
1 parent 3c11e03 commit 20363a4

File tree

7 files changed

+82
-10
lines changed

7 files changed

+82
-10
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ GOFLAGS :=
3838
TAGS :=
3939
LDFLAGS := "-w -s -X 'k8s.io/component-base/version.gitVersion=$(VERSION)' -X 'k8s.io/cloud-provider-openstack/pkg/version.Version=$(VERSION)'"
4040
GOX_LDFLAGS := $(shell echo "$(LDFLAGS) -extldflags \"-static\"")
41-
REGISTRY ?= registry.k8s.io/provider-os
41+
REGISTRY ?= reg.infra.ske.eu01.stackit.cloud/stackitcloud
4242
IMAGE_OS ?= linux
4343
IMAGE_NAMES ?= openstack-cloud-controller-manager \
4444
cinder-csi-plugin \

pkg/csi/cinder/controllerserver.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package cinder
1919
import (
2020
"fmt"
2121
"strconv"
22+
"time"
2223

2324
"github.com/container-storage-interface/spec/lib/go/csi"
2425
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/snapshots"
@@ -29,6 +30,7 @@ import (
2930
"google.golang.org/grpc/status"
3031
"google.golang.org/protobuf/types/known/timestamppb"
3132

33+
"k8s.io/apimachinery/pkg/util/wait"
3234
"k8s.io/cloud-provider-openstack/pkg/csi/cinder/openstack"
3335
"k8s.io/cloud-provider-openstack/pkg/util"
3436
cpoerrors "k8s.io/cloud-provider-openstack/pkg/util/errors"
@@ -93,12 +95,16 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
9395
if volSizeGB != volumes[0].Size {
9496
return nil, status.Error(codes.AlreadyExists, "Volume Already exists with same name and different capacity")
9597
}
98+
99+
if volumes[0].Status != openstack.VolumeAvailableStatus {
100+
return nil, status.Error(codes.Internal, fmt.Sprintf("Volume %s is not in available state", volumes[0].ID))
101+
}
102+
96103
klog.V(4).Infof("Volume %s already exists in Availability Zone: %s of size %d GiB", volumes[0].ID, volumes[0].AvailabilityZone, volumes[0].Size)
97104
return getCreateVolumeResponse(&volumes[0], ignoreVolumeAZ, req.GetAccessibilityRequirements()), nil
98105
} else if len(volumes) > 1 {
99106
klog.V(3).Infof("found multiple existing volumes with selected name (%s) during create", volName)
100107
return nil, status.Error(codes.Internal, "Multiple volumes reported by Cinder with same name")
101-
102108
}
103109

104110
// Volume Create
@@ -136,11 +142,21 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
136142
}
137143

138144
vol, err := cloud.CreateVolume(volName, volSizeGB, volType, volAvailability, snapshotID, sourcevolID, &properties)
139-
140145
if err != nil {
141146
klog.Errorf("Failed to CreateVolume: %v", err)
142147
return nil, status.Error(codes.Internal, fmt.Sprintf("CreateVolume failed with error %v", err))
148+
}
143149

150+
targetStatus := []string{openstack.VolumeAvailableStatus}
151+
err = cloud.WaitVolumeTargetStatusWithCustomBackoff(vol.ID, targetStatus,
152+
&wait.Backoff{
153+
Duration: 20 * time.Second,
154+
Steps: 5,
155+
Factor: 1.28,
156+
})
157+
if err != nil {
158+
klog.Errorf("Failed to WaitVolumeTargetStatus of volume %s: %v", vol.ID, err)
159+
return nil, status.Error(codes.Internal, fmt.Sprintf("CreateVolume Volume %s failed getting available in time: %v", vol.ID, err))
144160
}
145161

146162
klog.V(4).Infof("CreateVolume: Successfully created volume %s in Availability Zone: %s of size %d GiB", vol.ID, vol.AvailabilityZone, vol.Size)

pkg/csi/cinder/controllerserver_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ func TestCreateVolume(t *testing.T) {
4949
osmock.On("CreateVolume", FakeVolName, mock.AnythingOfType("int"), FakeVolType, FakeAvailability, "", "", &properties).Return(&FakeVol, nil)
5050

5151
osmock.On("GetVolumesByName", FakeVolName).Return(FakeVolListEmpty, nil)
52+
osmock.On("WaitVolumeTargetStatusWithCustomBackoff", mock.Anything, mock.Anything, mock.Anything).Return(nil)
5253
// Init assert
5354
assert := assert.New(t)
5455

pkg/csi/cinder/openstack/openstack.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
2929
"github.com/spf13/pflag"
3030
gcfg "gopkg.in/gcfg.v1"
31+
"k8s.io/apimachinery/pkg/util/wait"
3132
"k8s.io/cloud-provider-openstack/pkg/client"
3233
"k8s.io/cloud-provider-openstack/pkg/metrics"
3334
"k8s.io/cloud-provider-openstack/pkg/util/metadata"
@@ -52,6 +53,7 @@ type IOpenStack interface {
5253
DetachVolume(instanceID, volumeID string) error
5354
WaitDiskDetached(instanceID string, volumeID string) error
5455
WaitVolumeTargetStatus(volumeID string, tStatus []string) error
56+
WaitVolumeTargetStatusWithCustomBackoff(volumeID string, tStatus []string, backoff *wait.Backoff) error
5557
GetAttachmentDiskPath(instanceID, volumeID string) (string, error)
5658
GetVolume(volumeID string) (*volumes.Volume, error)
5759
GetVolumesByName(name string) ([]volumes.Volume, error)

pkg/csi/cinder/openstack/openstack_mock.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes"
2222
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
2323
"github.com/stretchr/testify/mock"
24+
"k8s.io/apimachinery/pkg/util/wait"
2425
"k8s.io/cloud-provider-openstack/pkg/util/metadata"
2526
)
2627

@@ -174,6 +175,20 @@ func (_m *OpenStackMock) WaitVolumeTargetStatus(volumeID string, tStatus []strin
174175
return r0
175176
}
176177

178+
// WaitVolumeTargetStatusWithCustomBackoff provides a mock function with given fields: volumeID, tStatus, backoff
179+
func (_m *OpenStackMock) WaitVolumeTargetStatusWithCustomBackoff(volumeID string, tStatus []string, backoff *wait.Backoff) error {
180+
ret := _m.Called(volumeID, tStatus, backoff)
181+
182+
var r0 error
183+
if rf, ok := ret.Get(0).(func(string, []string, *wait.Backoff) error); ok {
184+
r0 = rf(volumeID, tStatus, backoff)
185+
} else {
186+
r0 = ret.Error(0)
187+
}
188+
189+
return r0
190+
}
191+
177192
// WaitDiskDetached provides a mock function with given fields: instanceID, volumeID
178193
func (_m *OpenStackMock) WaitDiskDetached(instanceID string, volumeID string) error {
179194
ret := _m.Called(instanceID, volumeID)

pkg/csi/cinder/openstack/openstack_volumes.go

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ const (
3939
operationFinishInitDelay = 1 * time.Second
4040
operationFinishFactor = 1.1
4141
operationFinishSteps = 10
42-
diskAttachInitDelay = 1 * time.Second
43-
diskAttachFactor = 1.2
44-
diskAttachSteps = 15
45-
diskDetachInitDelay = 1 * time.Second
46-
diskDetachFactor = 1.2
47-
diskDetachSteps = 13
42+
diskAttachInitDelay = 7 * time.Second
43+
diskAttachFactor = 1.4
44+
diskAttachSteps = 10
45+
diskDetachInitDelay = 7 * time.Second
46+
diskDetachFactor = 1.4
47+
diskDetachSteps = 10
4848
volumeDescription = "Created by OpenStack Cinder CSI driver"
4949
)
5050

@@ -203,6 +203,12 @@ func (os *OpenStack) AttachVolume(instanceID, volumeID string) (string, error) {
203203
return "", fmt.Errorf("failed to attach %s volume to %s compute: %v", volumeID, instanceID, err)
204204
}
205205

206+
//redundant waitDiskAttached, workaround for raise condition in backend
207+
err = os.WaitDiskAttached(instanceID, volumeID)
208+
if err != nil {
209+
return "", err
210+
}
211+
206212
return volume.ID, nil
207213
}
208214

@@ -225,7 +231,7 @@ func (os *OpenStack) WaitDiskAttached(instanceID string, volumeID string) error
225231
})
226232

227233
if wait.Interrupted(err) {
228-
err = fmt.Errorf("Volume %q failed to be attached within the alloted time", volumeID)
234+
err = fmt.Errorf("Volume %q failed to be attached within the allowed time", volumeID)
229235
}
230236

231237
return err
@@ -264,6 +270,33 @@ func (os *OpenStack) WaitVolumeTargetStatus(volumeID string, tStatus []string) e
264270
return waitErr
265271
}
266272

273+
// WaitVolumeTargetStatusWithCustomBackoff waits for volume to be in target state with custom backoff
274+
func (os *OpenStack) WaitVolumeTargetStatusWithCustomBackoff(volumeID string, tStatus []string, backoff *wait.Backoff) error {
275+
waitErr := wait.ExponentialBackoff(*backoff, func() (bool, error) {
276+
vol, err := os.GetVolume(volumeID)
277+
if err != nil {
278+
return false, err
279+
}
280+
for _, t := range tStatus {
281+
if vol.Status == t {
282+
return true, nil
283+
}
284+
}
285+
for _, eState := range volumeErrorStates {
286+
if vol.Status == eState {
287+
return false, fmt.Errorf("Volume is in Error State : %s", vol.Status)
288+
}
289+
}
290+
return false, nil
291+
})
292+
293+
if waitErr == wait.ErrWaitTimeout {
294+
waitErr = fmt.Errorf("Timeout on waiting for volume %s status to be in %v", volumeID, tStatus)
295+
}
296+
297+
return waitErr
298+
}
299+
267300
// DetachVolume detaches given cinder volume from the compute
268301
func (os *OpenStack) DetachVolume(instanceID, volumeID string) error {
269302
volume, err := os.GetVolume(volumeID)

tests/sanity/cinder/fakecloud.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/snapshots"
1111
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes"
1212
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
13+
"k8s.io/apimachinery/pkg/util/wait"
1314
"k8s.io/cloud-provider-openstack/pkg/csi/cinder"
1415
"k8s.io/cloud-provider-openstack/pkg/csi/cinder/openstack"
1516
"k8s.io/cloud-provider-openstack/pkg/util/metadata"
@@ -115,6 +116,10 @@ func (cloud *cloud) WaitVolumeTargetStatus(volumeID string, tStatus []string) er
115116
return nil
116117
}
117118

119+
func (cloud *cloud) WaitVolumeTargetStatusWithCustomBackoff(volumeID string, tStatus []string, backoff *wait.Backoff) error {
120+
return nil
121+
}
122+
118123
func (cloud *cloud) GetAttachmentDiskPath(instanceID, volumeID string) (string, error) {
119124
return cinder.FakeDevicePath, nil
120125
}

0 commit comments

Comments
 (0)