@@ -29,7 +29,10 @@ import (
29
29
"k8s.io/utils/mount"
30
30
)
31
31
32
- const TopologyKeyNode = "topology.hostpath.csi/node"
32
+ const (
33
+ TopologyKeyNode = "topology.hostpath.csi/node"
34
+ ephemeralContextKey = "csi.storage.k8s.io/ephemeral"
35
+ )
33
36
34
37
type hostPathNode struct {
35
38
cfg * Config
@@ -135,7 +138,15 @@ func (hpn *hostPathNode) mountVolume(targetPath string, req *csi.NodePublishVolu
135
138
storagePoolName := getStoragePoolNameFromMap (req .GetVolumeContext ())
136
139
137
140
mounter := hpn .cfg .Mounter
138
- path := filepath .Join (hpn .cfg .StoragePoolDataDir [storagePoolName ], volumeId )
141
+ path := ""
142
+ if isEphemeralVolumeRequest (req ) {
143
+ path = hpn .getEphemeralVolumePath (storagePoolName , volumeId )
144
+ if err := CreateVolume (filepath .Dir (path ), volumeId ); err != nil {
145
+ return fmt .Errorf ("failed to create ephemeral volume %v: %w" , volumeId , err )
146
+ }
147
+ } else {
148
+ path = filepath .Join (hpn .cfg .StoragePoolDataDir [storagePoolName ], volumeId )
149
+ }
139
150
140
151
if err := mounter .Mount (path , targetPath , fsType , options ); err != nil {
141
152
var errList strings.Builder
@@ -145,11 +156,33 @@ func (hpn *hostPathNode) mountVolume(targetPath string, req *csi.NodePublishVolu
145
156
errList .WriteString (err .Error ())
146
157
}
147
158
errList .WriteString (fmt .Sprintf ("%v" , fileInfo .Mode ()))
159
+ if isEphemeralVolumeRequest (req ) {
160
+ if rmErr := os .RemoveAll (path ); rmErr != nil && ! os .IsNotExist (rmErr ) {
161
+ errList .WriteString (fmt .Sprintf (" :%s" , rmErr .Error ()))
162
+ }
163
+ }
164
+
148
165
return fmt .Errorf ("failed to mount device: %s at %s: %s" , path , targetPath , errList .String ())
149
166
}
150
167
return nil
151
168
}
152
169
170
+ func isEphemeralVolumeRequest (req * csi.NodePublishVolumeRequest ) bool {
171
+ return req .GetVolumeContext ()[ephemeralContextKey ] == "true"
172
+ }
173
+
174
+ func isEphemeralVolumeId (volumeId string ) bool {
175
+ return strings .HasPrefix (volumeId , "csi" )
176
+ }
177
+
178
+ func (hpn * hostPathNode ) getEphemeralVolumePath (storagePoolName , volumeId string ) string {
179
+ storagePoolPath := hpn .cfg .StoragePoolDataDir [storagePoolName ]
180
+ if len (storagePoolPath ) == 0 {
181
+ storagePoolPath = hpn .cfg .StoragePoolDataDir [hpn .cfg .DefaultStoragePoolName ]
182
+ }
183
+ return filepath .Join (storagePoolPath , volumeId )
184
+ }
185
+
153
186
func (hpn * hostPathNode ) validateNodeUnpublishRequest (req * csi.NodeUnpublishVolumeRequest ) error {
154
187
// Check arguments
155
188
if len (req .GetVolumeId ()) == 0 {
@@ -162,6 +195,9 @@ func (hpn *hostPathNode) validateNodeUnpublishRequest(req *csi.NodeUnpublishVolu
162
195
}
163
196
164
197
func (hpn * hostPathNode ) NodeUnpublishVolume (ctx context.Context , req * csi.NodeUnpublishVolumeRequest ) (* csi.NodeUnpublishVolumeResponse , error ) {
198
+ if req != nil {
199
+ klog .V (3 ).Infof ("Node Unpublish Request: %+v" , * req )
200
+ }
165
201
if err := hpn .validateNodeUnpublishRequest (req ); err != nil {
166
202
return nil , err
167
203
}
@@ -188,10 +224,38 @@ func (hpn *hostPathNode) NodeUnpublishVolume(ctx context.Context, req *csi.NodeU
188
224
return nil , fmt .Errorf ("remove target path: %w" , err )
189
225
}
190
226
klog .V (4 ).Infof ("hostpath: volume %s has been unpublished." , targetPath )
191
-
227
+ if isEphemeralVolumeId (req .GetVolumeId ()) {
228
+ if err := hpn .removeEphemeralPath (req .GetVolumeId ()); err != nil {
229
+ return nil , fmt .Errorf ("failed to delete ephemeral volume: %s, %v" , req .GetVolumeId (), err )
230
+ }
231
+ }
192
232
return & csi.NodeUnpublishVolumeResponse {}, nil
193
233
}
194
234
235
+ func (hpn * hostPathNode ) removeEphemeralPath (volumeId string ) error {
236
+ volumeDirs , err := hpn .getVolumeDirectories ()
237
+ if err != nil {
238
+ return err
239
+ }
240
+ volumePath := ""
241
+ for _ , volumeDir := range volumeDirs {
242
+ if filepath .Base (volumeDir ) == volumeId {
243
+ volumePath = volumeDir
244
+ }
245
+ }
246
+ if volumePath != "" {
247
+ if err := DeleteVolume (filepath .Dir (volumePath ), volumeId ); err != nil {
248
+ return fmt .Errorf ("failed to delete ephemeral volume %s: %v" , volumeId , err )
249
+ }
250
+ klog .V (4 ).Infof ("ephemeral volume %v successfully deleted" , volumeId )
251
+ }
252
+ return nil
253
+ }
254
+
255
+ func (hpn * hostPathNode ) getVolumeDirectories () ([]string , error ) {
256
+ return getVolumeDirectories (hpn .cfg .StoragePoolDataDir )
257
+ }
258
+
195
259
func (hpn * hostPathNode ) NodeStageVolume (ctx context.Context , req * csi.NodeStageVolumeRequest ) (* csi.NodeStageVolumeResponse , error ) {
196
260
return nil , status .Error (codes .Unimplemented , "NodeStageVolume is not supported" )
197
261
}
0 commit comments