Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
a7e3d60e
Commit
a7e3d60e
authored
Jun 07, 2018
by
Jan Safranek
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix UnmountDevice with deleted pod.
When a pod is deleted, kubelet can't read VolumeAttachment objects. It should cache all information in a json file.
parent
1a1c0bab
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
108 additions
and
34 deletions
+108
-34
csi_attacher.go
pkg/volume/csi/csi_attacher.go
+44
-4
csi_attacher_test.go
pkg/volume/csi/csi_attacher_test.go
+64
-30
No files found.
pkg/volume/csi/csi_attacher.go
View file @
a7e3d60e
...
@@ -269,6 +269,25 @@ func (c *csiAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMo
...
@@ -269,6 +269,25 @@ func (c *csiAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMo
return
err
return
err
}
}
dataDir
:=
filepath
.
Dir
(
deviceMountPath
)
if
err
:=
os
.
MkdirAll
(
dataDir
,
0750
);
err
!=
nil
{
glog
.
Error
(
log
(
"attacher.MountDevice failed to create dir %#v: %v"
,
dataDir
,
err
))
return
err
}
data
:=
map
[
string
]
string
{
volDataKey
.
volHandle
:
csiSource
.
VolumeHandle
,
volDataKey
.
driverName
:
csiSource
.
Driver
,
}
if
err
:=
saveVolumeData
(
dataDir
,
volDataFileName
,
data
);
err
!=
nil
{
glog
.
Error
(
log
(
"failed to save volume info data: %v"
,
err
))
if
err
:=
os
.
RemoveAll
(
dataDir
);
err
!=
nil
{
glog
.
Error
(
log
(
"failed to remove dir after error [%s]: %v"
,
dataDir
,
err
))
return
err
}
return
err
}
if
c
.
csiClient
==
nil
{
if
c
.
csiClient
==
nil
{
c
.
csiClient
=
newCsiDriverClient
(
csiSource
.
Driver
)
c
.
csiClient
=
newCsiDriverClient
(
csiSource
.
Driver
)
}
}
...
@@ -462,10 +481,21 @@ func (c *csiAttacher) UnmountDevice(deviceMountPath string) error {
...
@@ -462,10 +481,21 @@ func (c *csiAttacher) UnmountDevice(deviceMountPath string) error {
glog
.
V
(
4
)
.
Info
(
log
(
"attacher.UnmountDevice(%s)"
,
deviceMountPath
))
glog
.
V
(
4
)
.
Info
(
log
(
"attacher.UnmountDevice(%s)"
,
deviceMountPath
))
// Setup
// Setup
driverName
,
volID
,
err
:=
getDriverAndVolNameFromDeviceMountPath
(
c
.
k8s
,
deviceMountPath
)
var
driverName
,
volID
string
if
err
!=
nil
{
dataDir
:=
filepath
.
Dir
(
deviceMountPath
)
glog
.
Errorf
(
log
(
"attacher.UnmountDevice failed to get driver and volume name from device mount path: %v"
,
err
))
data
,
err
:=
loadVolumeData
(
dataDir
,
volDataFileName
)
return
err
if
err
==
nil
{
driverName
=
data
[
volDataKey
.
driverName
]
volID
=
data
[
volDataKey
.
volHandle
]
}
else
{
glog
.
Error
(
log
(
"UnmountDevice failed to load volume data file [%s]: %v"
,
dataDir
,
err
))
// The volume might have been mounted by old CSI volume plugin. Fall back to the old behavior: read PV from API server
driverName
,
volID
,
err
=
getDriverAndVolNameFromDeviceMountPath
(
c
.
k8s
,
deviceMountPath
)
if
err
!=
nil
{
glog
.
Errorf
(
log
(
"attacher.UnmountDevice failed to get driver and volume name from device mount path: %v"
,
err
))
return
err
}
}
}
if
c
.
csiClient
==
nil
{
if
c
.
csiClient
==
nil
{
...
@@ -483,6 +513,11 @@ func (c *csiAttacher) UnmountDevice(deviceMountPath string) error {
...
@@ -483,6 +513,11 @@ func (c *csiAttacher) UnmountDevice(deviceMountPath string) error {
}
}
if
!
stageUnstageSet
{
if
!
stageUnstageSet
{
glog
.
Infof
(
log
(
"attacher.UnmountDevice STAGE_UNSTAGE_VOLUME capability not set. Skipping UnmountDevice..."
))
glog
.
Infof
(
log
(
"attacher.UnmountDevice STAGE_UNSTAGE_VOLUME capability not set. Skipping UnmountDevice..."
))
// Just delete the global directory + json file
if
err
:=
removeMountDir
(
c
.
plugin
,
deviceMountPath
);
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to clean up gloubal mount %s: %s"
,
dataDir
,
err
)
}
return
nil
return
nil
}
}
...
@@ -496,6 +531,11 @@ func (c *csiAttacher) UnmountDevice(deviceMountPath string) error {
...
@@ -496,6 +531,11 @@ func (c *csiAttacher) UnmountDevice(deviceMountPath string) error {
return
err
return
err
}
}
// Delete the global directory + json file
if
err
:=
removeMountDir
(
c
.
plugin
,
deviceMountPath
);
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to clean up gloubal mount %s: %s"
,
dataDir
,
err
)
}
glog
.
V
(
4
)
.
Infof
(
log
(
"attacher.UnmountDevice successfully requested NodeStageVolume [%s]"
,
deviceMountPath
))
glog
.
V
(
4
)
.
Infof
(
log
(
"attacher.UnmountDevice successfully requested NodeStageVolume [%s]"
,
deviceMountPath
))
return
nil
return
nil
}
}
...
...
pkg/volume/csi/csi_attacher_test.go
View file @
a7e3d60e
...
@@ -18,6 +18,7 @@ package csi
...
@@ -18,6 +18,7 @@ package csi
import
(
import
(
"fmt"
"fmt"
"io/ioutil"
"os"
"os"
"path/filepath"
"path/filepath"
"testing"
"testing"
...
@@ -610,45 +611,50 @@ func TestAttacherUnmountDevice(t *testing.T) {
...
@@ -610,45 +611,50 @@ func TestAttacherUnmountDevice(t *testing.T) {
testName
string
testName
string
volID
string
volID
string
deviceMountPath
string
deviceMountPath
string
jsonFile
string
createPV
bool
stageUnstageSet
bool
stageUnstageSet
bool
shouldFail
bool
shouldFail
bool
}{
}{
{
{
testName
:
"normal"
,
testName
:
"normal
, json file exists
"
,
volID
:
"project/zone/test-vol1"
,
volID
:
"project/zone/test-vol1"
,
deviceMountPath
:
"/tmp/csi-test049507108/plugins/csi/pv/test-pv-name/globalmount"
,
deviceMountPath
:
"plugins/csi/pv/test-pv-name/globalmount"
,
jsonFile
:
`{"driverName": "csi", "volumeHandle":"project/zone/test-vol1"}`
,
createPV
:
false
,
stageUnstageSet
:
true
,
stageUnstageSet
:
true
,
},
},
{
{
testName
:
"no
device mount path
"
,
testName
:
"no
rmal, json file doesn't exist -> use PV
"
,
volID
:
"project/zone/test-vol1"
,
volID
:
"project/zone/test-vol1"
,
deviceMountPath
:
""
,
deviceMountPath
:
"
plugins/csi/pv/test-pv-name/globalmount
"
,
stageUnstageSet
:
true
,
jsonFile
:
""
,
shouldFail
:
true
,
createPV
:
true
,
},
},
{
{
testName
:
"
missing part of device mount path
"
,
testName
:
"
invalid json -> use PV
"
,
volID
:
"project/zone/test-vol1"
,
volID
:
"project/zone/test-vol1"
,
deviceMountPath
:
"/tmp/csi-test049507108/plugins/csi/pv/test-pv-name/globalmount"
,
deviceMountPath
:
"plugins/csi/pv/test-pv-name/globalmount"
,
jsonFile
:
`{"driverName"}}`
,
createPV
:
true
,
stageUnstageSet
:
true
,
stageUnstageSet
:
true
,
shouldFail
:
true
,
},
},
{
{
testName
:
"test volume name mismatch"
,
testName
:
"no json, no PV.volID"
,
volID
:
"project/zone/test-vol1"
,
volID
:
""
,
deviceMountPath
:
"/tmp/csi-test049507108/plugins/csi/pv/test-pv-name/globalmount"
,
deviceMountPath
:
"plugins/csi/pv/test-pv-name/globalmount"
,
stageUnstageSet
:
true
,
jsonFile
:
""
,
createPV
:
true
,
shouldFail
:
true
,
shouldFail
:
true
,
},
},
{
{
testName
:
"
stage_unstage not set
"
,
testName
:
"
no json, no PV
"
,
volID
:
"project/zone/test-vol1"
,
volID
:
"project/zone/test-vol1"
,
deviceMountPath
:
"/tmp/csi-test049507108/plugins/csi/pv/test-pv-name/globalmount"
,
deviceMountPath
:
"plugins/csi/pv/test-pv-name/globalmount"
,
stageUnstageSet
:
false
,
jsonFile
:
""
,
},
createPV
:
false
,
{
stageUnstageSet
:
true
,
testName
:
"stage_unstage not set no vars should not fail"
,
shouldFail
:
true
,
stageUnstageSet
:
false
,
},
},
}
}
...
@@ -665,29 +671,45 @@ func TestAttacherUnmountDevice(t *testing.T) {
...
@@ -665,29 +671,45 @@ func TestAttacherUnmountDevice(t *testing.T) {
csiAttacher
:=
attacher
.
(
*
csiAttacher
)
csiAttacher
:=
attacher
.
(
*
csiAttacher
)
csiAttacher
.
csiClient
=
setupClient
(
t
,
tc
.
stageUnstageSet
)
csiAttacher
.
csiClient
=
setupClient
(
t
,
tc
.
stageUnstageSet
)
if
tc
.
deviceMountPath
!=
""
{
tc
.
deviceMountPath
=
filepath
.
Join
(
tmpDir
,
tc
.
deviceMountPath
)
}
// Add the volume to NodeStagedVolumes
// Add the volume to NodeStagedVolumes
cdc
:=
csiAttacher
.
csiClient
.
(
*
fakeCsiDriverClient
)
cdc
:=
csiAttacher
.
csiClient
.
(
*
fakeCsiDriverClient
)
cdc
.
nodeClient
.
AddNodeStagedVolume
(
tc
.
volID
,
tc
.
deviceMountPath
)
cdc
.
nodeClient
.
AddNodeStagedVolume
(
tc
.
volID
,
tc
.
deviceMountPath
)
// Make the PV for this object
// Make JSON for this object
if
tc
.
deviceMountPath
!=
""
{
if
err
:=
os
.
MkdirAll
(
tc
.
deviceMountPath
,
0755
);
err
!=
nil
{
t
.
Fatalf
(
"error creating directory %s: %s"
,
tc
.
deviceMountPath
,
err
)
}
}
dir
:=
filepath
.
Dir
(
tc
.
deviceMountPath
)
dir
:=
filepath
.
Dir
(
tc
.
deviceMountPath
)
// dir is now /var/lib/kubelet/plugins/kubernetes.io/csi/pv/{pvname}
if
tc
.
jsonFile
!=
""
{
pvName
:=
filepath
.
Base
(
dir
)
dataPath
:=
filepath
.
Join
(
dir
,
volDataFileName
)
pv
:=
makeTestPV
(
pvName
,
5
,
"csi"
,
tc
.
volID
)
if
err
:=
ioutil
.
WriteFile
(
dataPath
,
[]
byte
(
tc
.
jsonFile
),
0644
);
err
!=
nil
{
_
,
err
:=
csiAttacher
.
k8s
.
CoreV1
()
.
PersistentVolumes
()
.
Create
(
pv
)
t
.
Fatalf
(
"error creating %s: %s"
,
dataPath
,
err
)
if
err
!=
nil
&&
!
tc
.
shouldFail
{
}
t
.
Fatalf
(
"Failed to create PV: %v"
,
err
)
}
if
tc
.
createPV
{
// Make the PV for this object
pvName
:=
filepath
.
Base
(
dir
)
pv
:=
makeTestPV
(
pvName
,
5
,
"csi"
,
tc
.
volID
)
_
,
err
:=
csiAttacher
.
k8s
.
CoreV1
()
.
PersistentVolumes
()
.
Create
(
pv
)
if
err
!=
nil
&&
!
tc
.
shouldFail
{
t
.
Fatalf
(
"Failed to create PV: %v"
,
err
)
}
}
}
// Run
// Run
err
=
csiAttacher
.
UnmountDevice
(
tc
.
deviceMountPath
)
err
:=
csiAttacher
.
UnmountDevice
(
tc
.
deviceMountPath
)
// Verify
// Verify
if
err
!=
nil
{
if
err
!=
nil
{
if
!
tc
.
shouldFail
{
if
!
tc
.
shouldFail
{
t
.
Errorf
(
"test should not fail, but error occurred: %v"
,
err
)
t
.
Errorf
(
"test should not fail, but error occurred: %v"
,
err
)
}
}
return
continue
}
}
if
err
==
nil
&&
tc
.
shouldFail
{
if
err
==
nil
&&
tc
.
shouldFail
{
t
.
Errorf
(
"test should fail, but no error occurred"
)
t
.
Errorf
(
"test should fail, but no error occurred"
)
...
@@ -710,6 +732,18 @@ func TestAttacherUnmountDevice(t *testing.T) {
...
@@ -710,6 +732,18 @@ func TestAttacherUnmountDevice(t *testing.T) {
t
.
Errorf
(
"could not find expected staged volume: %s"
,
tc
.
volID
)
t
.
Errorf
(
"could not find expected staged volume: %s"
,
tc
.
volID
)
}
}
if
tc
.
jsonFile
!=
""
&&
!
tc
.
shouldFail
{
dataPath
:=
filepath
.
Join
(
dir
,
volDataFileName
)
if
_
,
err
:=
os
.
Stat
(
dataPath
);
!
os
.
IsNotExist
(
err
)
{
if
err
!=
nil
{
t
.
Errorf
(
"error checking file %s: %s"
,
dataPath
,
err
)
}
else
{
t
.
Errorf
(
"json file %s should not exists, but it does"
,
dataPath
)
}
}
else
{
t
.
Logf
(
"json file %s was correctly removed"
,
dataPath
)
}
}
}
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment