Skip to content

Commit e7effcb

Browse files
committed
fix: change the way of listing existing volumes
1 parent b14569a commit e7effcb

File tree

6 files changed

+112
-53
lines changed

6 files changed

+112
-53
lines changed

cmd/hostpathplugin/main.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,9 @@ func handle() {
6565
os.Exit(1)
6666
}
6767

68-
driver.Run()
68+
if err := driver.Run(); err != nil {
69+
fmt.Printf("Failed to run driver: %s", err.Error())
70+
os.Exit(1)
71+
72+
}
6973
}

go.mod

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,13 @@ require (
77
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
88
github.com/golang/protobuf v1.4.2
99
github.com/google/gofuzz v1.2.0 // indirect
10-
github.com/imdario/mergo v0.3.11 // indirect
1110
github.com/kubernetes-csi/csi-lib-utils v0.3.0
1211
github.com/pborman/uuid v0.0.0-20180906182336-adf5a7427709
1312
github.com/stretchr/testify v1.4.0
1413
golang.org/x/net v0.0.0-20200707034311-ab3426394381
1514
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect
1615
google.golang.org/grpc v1.27.0
17-
k8s.io/api v0.19.1
18-
k8s.io/apimachinery v0.19.1
16+
gopkg.in/yaml.v2 v2.3.0 // indirect
1917
k8s.io/client-go v0.19.1
2018
k8s.io/kubernetes v1.12.2
2119
k8s.io/utils v0.0.0-20201104234853-8146046b121e

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,6 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
105105
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
106106
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
107107
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
108-
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
109-
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
110108
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
111109
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
112110
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=

pkg/hostpath/healthcheck.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ import (
1515
const (
1616
// sourcePathPrefix should be specified by the csi-data-dir volume.
1717
// You can change it by modifying the volume path of csi-data-dir volume.
18-
sourcePathPrefix = "/csi-data-dir/"
19-
podVolumeTargetPath = "/var/lib/kubelet/pods"
18+
sourcePathPrefix = "/csi-data-dir/"
19+
podVolumeTargetPath = "/var/lib/kubelet/pods"
20+
csiSignOfVolumeTargetPath = "kubernetes.io~csi/pvc"
2021
)
2122

2223
type MountPointInfo struct {

pkg/hostpath/healthcheck_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,3 +330,15 @@ func TestParseMountInfo(t *testing.T) {
330330
assert.Nil(t, err)
331331
assert.NotNil(t, containerFileSystems)
332332
}
333+
334+
func TestFilterVolumeName(t *testing.T) {
335+
targetPath := "/var/lib/kubelet/pods/3440e8ee-10de-11eb-8895-fa163feebd84/volumes/kubernetes.io~csi/pvc-33d023c7-10de-11eb-8895-fa163feebd84/mount"
336+
volumeName := filterVolumeName(targetPath)
337+
assert.Equal(t, "pvc-33d023c7-10de-11eb-8895-fa163feebd84", volumeName)
338+
}
339+
340+
func TestFilterVolumeID(t *testing.T) {
341+
sourcePath := "/dev/vda2[/var/lib/csi-hostpath-data/39267558-10de-11eb-8fb9-0a58ac120605]"
342+
volumeID := filterVolumeID(sourcePath)
343+
assert.Equal(t, "39267558-10de-11eb-8fb9-0a58ac120605", volumeID)
344+
}

pkg/hostpath/hostpath.go

Lines changed: 91 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,23 @@ limitations under the License.
1717
package hostpath
1818

1919
import (
20-
"context"
2120
"errors"
2221
"fmt"
2322
"io"
2423
"io/ioutil"
2524
"os"
25+
"os/exec"
2626
"path/filepath"
27+
"regexp"
2728
"sort"
2829
"strings"
2930

3031
"github.com/golang/glog"
3132
timestamp "github.com/golang/protobuf/ptypes/timestamp"
3233
"google.golang.org/grpc/codes"
3334
"google.golang.org/grpc/status"
34-
v1 "k8s.io/api/core/v1"
35-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3635
"k8s.io/client-go/kubernetes"
37-
"k8s.io/client-go/tools/clientcmd"
36+
fs "k8s.io/kubernetes/pkg/volume/util/fs"
3837
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
3938
utilexec "k8s.io/utils/exec"
4039
)
@@ -129,26 +128,13 @@ func NewHostPathDriver(driverName, nodeID, endpoint string, ephemeral bool, maxV
129128
glog.Infof("Driver: %v ", driverName)
130129
glog.Infof("Version: %s", vendorVersion)
131130

132-
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
133-
if err != nil {
134-
fmt.Printf("Failed to build kubeconfig: %s", err.Error())
135-
os.Exit(1)
136-
}
137-
138-
clientset, err := kubernetes.NewForConfig(config)
139-
if err != nil {
140-
fmt.Printf("Faild to create k8s client: %s", err.Error())
141-
os.Exit(1)
142-
}
143-
144131
return &hostPath{
145132
name: driverName,
146133
version: vendorVersion,
147134
nodeID: nodeID,
148135
endpoint: endpoint,
149136
ephemeral: ephemeral,
150137
maxVolumesPerNode: maxVolumesPerNode,
151-
kclient: clientset,
152138
}, nil
153139
}
154140

@@ -181,10 +167,12 @@ func discoverExistingSnapshots() {
181167
}
182168
}
183169

184-
func (hp *hostPath) Run() {
185-
// Initialize existing volumes
186-
hp.initExistingVolumes()
170+
func (hp *hostPath) Run() error {
187171
// Create GRPC servers
172+
if err := initialExistingVolumes(); err != nil {
173+
return err
174+
}
175+
188176
hp.ids = NewIdentityServer(hp.name, hp.version)
189177
hp.ns = NewNodeServer(hp.nodeID, hp.ephemeral, hp.maxVolumesPerNode)
190178
hp.cs = NewControllerServer(hp.ephemeral, hp.nodeID)
@@ -193,32 +181,8 @@ func (hp *hostPath) Run() {
193181
s := NewNonBlockingGRPCServer()
194182
s.Start(hp.endpoint, hp.ids, hp.cs, hp.ns)
195183
s.Wait()
196-
}
197-
198-
func (hp *hostPath) initExistingVolumes() {
199-
pvList, err := hp.kclient.CoreV1().PersistentVolumes().List(context.Background(), metav1.ListOptions{})
200-
if err != nil {
201-
glog.V(3).Infof("Failed to get pv: %s", err.Error())
202-
os.Exit(1)
203-
}
204-
205-
for _, pv := range pvList.Items {
206-
volAccessType := mountAccess
207-
if *pv.Spec.VolumeMode == v1.PersistentVolumeBlock {
208-
volAccessType = blockAccess
209-
}
210-
211-
hostPathVolumes[pv.Spec.CSI.VolumeHandle] = hostPathVolume{
212-
VolName: pv.Name,
213-
VolID: pv.Spec.CSI.VolumeHandle,
214-
VolSize: pv.Spec.Capacity.Storage().Value(),
215-
VolPath: getVolumePath(pv.Spec.CSI.VolumeHandle),
216-
VolAccessType: volAccessType,
217-
}
218-
}
219184

220-
glog.V(3).Infof("The existing volume list is: %+v\n", hostPathVolumes)
221-
return
185+
return nil
222186
}
223187

224188
func getVolumeByID(volumeID string) (hostPathVolume, error) {
@@ -455,3 +419,85 @@ func getSortedVolumeIDs() []string {
455419
sort.Strings(ids)
456420
return ids
457421
}
422+
423+
func filterVolumeName(targetPath string) string {
424+
pathItems := strings.Split(targetPath, "kubernetes.io~csi/")
425+
if len(pathItems) < 2 {
426+
return ""
427+
}
428+
429+
return strings.TrimSuffix(pathItems[1], "/mount")
430+
}
431+
432+
func filterVolumeID(sourcePath string) string {
433+
volumeSourcePathRegex := regexp.MustCompile(`\[(.*)\]`)
434+
volumeSP := string(volumeSourcePathRegex.Find([]byte(sourcePath)))
435+
if volumeSP == "" {
436+
return ""
437+
}
438+
439+
return strings.TrimSuffix(strings.TrimPrefix(volumeSP, "[/var/lib/csi-hostpath-data/"), "]")
440+
}
441+
442+
func parseVolumeInfo(volume MountPointInfo) (*hostPathVolume, error) {
443+
volumeName := filterVolumeName(volume.Target)
444+
volumeID := filterVolumeID(volume.Source)
445+
sourcePath := getSourcePath(volumeID)
446+
_, fscapacity, _, _, _, _, err := fs.FsInfo(sourcePath)
447+
if err != nil {
448+
return nil, fmt.Errorf("failed to get capacity info: %+v", err)
449+
}
450+
451+
hp := hostPathVolume{
452+
VolName: volumeName,
453+
VolID: volumeID,
454+
VolSize: fscapacity,
455+
VolPath: getVolumePath(volumeID),
456+
VolAccessType: mountAccess,
457+
}
458+
459+
return &hp, nil
460+
}
461+
462+
func initialExistingVolumes() error {
463+
cmdPath := locateCommandPath("findmnt")
464+
out, err := exec.Command(cmdPath, "--json").CombinedOutput()
465+
if err != nil {
466+
glog.V(3).Infof("failed to execute command: %+v", cmdPath)
467+
return err
468+
}
469+
470+
if len(out) < 1 {
471+
return fmt.Errorf("mount point info is nil")
472+
}
473+
474+
mountInfos, err := parseMountInfo([]byte(out))
475+
if err != nil {
476+
return fmt.Errorf("failed to parse the mount infos: %+v", err)
477+
}
478+
479+
mountInfosOfPod := MountPointInfo{}
480+
for _, mountInfo := range mountInfos {
481+
if mountInfo.Target == podVolumeTargetPath {
482+
mountInfosOfPod = mountInfo
483+
break
484+
}
485+
}
486+
487+
// getting existing volumes based on the mount point infos.
488+
// It's a temporary solution to recall volumes.
489+
for _, pv := range mountInfosOfPod.ContainerFileSystem {
490+
if !strings.Contains(pv.Target, csiSignOfVolumeTargetPath) {
491+
continue
492+
}
493+
494+
hp, err := parseVolumeInfo(pv)
495+
if err != nil {
496+
return err
497+
}
498+
499+
hostPathVolumes[hp.VolID] = *hp
500+
}
501+
502+
return nil
503+
}

0 commit comments

Comments
 (0)