@@ -17,6 +17,7 @@ limitations under the License.
17
17
package azure
18
18
19
19
import (
20
+ "context"
20
21
"fmt"
21
22
"time"
22
23
@@ -26,6 +27,7 @@ import (
26
27
"k8s.io/apimachinery/pkg/types"
27
28
kwait "k8s.io/apimachinery/pkg/util/wait"
28
29
cloudprovider "k8s.io/cloud-provider"
30
+ "k8s.io/utils/keymutex"
29
31
)
30
32
31
33
const (
@@ -50,6 +52,9 @@ var defaultBackOff = kwait.Backoff{
50
52
Jitter : 0.0 ,
51
53
}
52
54
55
+ // acquire lock to attach/detach disk in one node
56
+ var diskOpMutex = keymutex .NewHashed (0 )
57
+
53
58
type controllerCommon struct {
54
59
subscriptionID string
55
60
location string
@@ -85,24 +90,72 @@ func (c *controllerCommon) getNodeVMSet(nodeName types.NodeName) (VMSet, error)
85
90
return ss , nil
86
91
}
87
92
88
- // AttachDisk attaches a vhd to vm. The vhd must exist, can be identified by diskName, diskURI, and lun .
89
- func (c * controllerCommon ) AttachDisk (isManagedDisk bool , diskName , diskURI string , nodeName types.NodeName , lun int32 , cachingMode compute.CachingTypes ) error {
93
+ // AttachDisk attaches a vhd to vm. The vhd must exist, can be identified by diskName, diskURI.
94
+ func (c * controllerCommon ) AttachDisk (isManagedDisk bool , diskName , diskURI string , nodeName types.NodeName , cachingMode compute.CachingTypes ) error {
90
95
vmset , err := c .getNodeVMSet (nodeName )
91
96
if err != nil {
92
97
return err
93
98
}
94
99
100
+ instanceid , err := c .cloud .InstanceID (context .TODO (), nodeName )
101
+ if err != nil {
102
+ klog .Warningf ("failed to get azure instance id (%v)" , err )
103
+ return fmt .Errorf ("failed to get azure instance id for node %q (%v)" , nodeName , err )
104
+ }
105
+
106
+ diskOpMutex .LockKey (instanceid )
107
+ defer diskOpMutex .UnlockKey (instanceid )
108
+
109
+ lun , err := c .GetNextDiskLun (nodeName )
110
+ if err != nil {
111
+ klog .Warningf ("no LUN available for instance %q (%v)" , nodeName , err )
112
+ return fmt .Errorf ("all LUNs are used, cannot attach volume (%s, %s) to instance %q (%v)" , diskName , diskURI , instanceid , err )
113
+ }
114
+
115
+ klog .V (2 ).Infof ("Trying to attach volume %q lun %d to node %q." , diskURI , lun , nodeName )
95
116
return vmset .AttachDisk (isManagedDisk , diskName , diskURI , nodeName , lun , cachingMode )
96
117
}
97
118
98
- // DetachDiskByName detaches a vhd from host. The vhd can be identified by diskName or diskURI.
99
- func (c * controllerCommon ) DetachDiskByName (diskName , diskURI string , nodeName types.NodeName ) error {
119
+ // DetachDisk detaches a disk from host. The vhd can be identified by diskName or diskURI.
120
+ func (c * controllerCommon ) DetachDisk (diskName , diskURI string , nodeName types.NodeName ) error {
100
121
vmset , err := c .getNodeVMSet (nodeName )
101
122
if err != nil {
102
123
return err
103
124
}
104
125
105
- return vmset .DetachDiskByName (diskName , diskURI , nodeName )
126
+ instanceid , err := c .cloud .InstanceID (context .TODO (), nodeName )
127
+ if err != nil {
128
+ klog .Warningf ("failed to get azure instance id (%v)" , err )
129
+ return fmt .Errorf ("failed to get azure instance id for node %q (%v)" , nodeName , err )
130
+ }
131
+
132
+ klog .V (2 ).Infof ("detach %v from node %q" , diskURI , nodeName )
133
+
134
+ // make the lock here as small as possible
135
+ diskOpMutex .LockKey (instanceid )
136
+ resp , err := vmset .DetachDisk (diskName , diskURI , nodeName )
137
+ diskOpMutex .UnlockKey (instanceid )
138
+
139
+ if c .cloud .CloudProviderBackoff && shouldRetryHTTPRequest (resp , err ) {
140
+ klog .V (2 ).Infof ("azureDisk - update backing off: detach disk(%s, %s), err: %v" , diskName , diskURI , err )
141
+ retryErr := kwait .ExponentialBackoff (c .cloud .requestBackoff (), func () (bool , error ) {
142
+ diskOpMutex .LockKey (instanceid )
143
+ resp , err := vmset .DetachDisk (diskName , diskURI , nodeName )
144
+ diskOpMutex .UnlockKey (instanceid )
145
+ return c .cloud .processHTTPRetryResponse (nil , "" , resp , err )
146
+ })
147
+ if retryErr != nil {
148
+ err = retryErr
149
+ klog .V (2 ).Infof ("azureDisk - update abort backoff: detach disk(%s, %s), err: %v" , diskName , diskURI , err )
150
+ }
151
+ }
152
+ if err != nil {
153
+ klog .Errorf ("azureDisk - detach disk(%s, %s) failed, err: %v" , diskName , diskURI , err )
154
+ } else {
155
+ klog .V (2 ).Infof ("azureDisk - detach disk(%s, %s) succeeded" , diskName , diskURI )
156
+ }
157
+
158
+ return err
106
159
}
107
160
108
161
// getNodeDataDisks invokes vmSet interfaces to get data disks for the node.
0 commit comments