1
16
17 package mount
18
19 import (
20 "os"
21 "path/filepath"
22 "sync"
23
24 "k8s.io/klog/v2"
25 )
26
27
28 type FakeMounter struct {
29 MountPoints []MountPoint
30 log []FakeAction
31
32 MountCheckErrors map[string]error
33
34
35 mutex sync.Mutex
36 UnmountFunc UnmountFunc
37 }
38
39
40 type UnmountFunc func(path string) error
41
42 var _ Interface = &FakeMounter{}
43
44 const (
45
46 FakeActionMount = "mount"
47
48 FakeActionUnmount = "unmount"
49 )
50
51
52 type FakeAction struct {
53 Action string
54 Target string
55 Source string
56 FSType string
57 }
58
59
60
61 func NewFakeMounter(mps []MountPoint) *FakeMounter {
62 return &FakeMounter{
63 MountPoints: mps,
64 }
65 }
66
67
68 func (f *FakeMounter) ResetLog() {
69 f.mutex.Lock()
70 defer f.mutex.Unlock()
71
72 f.log = []FakeAction{}
73 }
74
75
76 func (f *FakeMounter) GetLog() []FakeAction {
77 f.mutex.Lock()
78 defer f.mutex.Unlock()
79
80 return f.log
81 }
82
83
84 func (f *FakeMounter) Mount(source string, target string, fstype string, options []string) error {
85 return f.MountSensitive(source, target, fstype, options, nil )
86 }
87
88
89
90
91
92
93 func (f *FakeMounter) MountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string) error {
94 f.mutex.Lock()
95 defer f.mutex.Unlock()
96
97 opts := []string{}
98
99 for _, option := range options {
100
101 if option == "bind" {
102
103
104
105
106
107
108
109
110
111
112
113 for _, mnt := range f.MountPoints {
114 if source == mnt.Path {
115 source = mnt.Device
116 break
117 }
118 }
119 }
120
121 opts = append(opts, option)
122 }
123
124
125 absTarget, err := filepath.EvalSymlinks(target)
126 if err != nil {
127 absTarget = target
128 }
129 f.MountPoints = append(f.MountPoints, MountPoint{Device: source, Path: absTarget, Type: fstype, Opts: append(opts, sensitiveOptions...)})
130 klog.V(5).Infof("Fake mounter: mounted %s to %s", source, absTarget)
131 f.log = append(f.log, FakeAction{Action: FakeActionMount, Target: absTarget, Source: source, FSType: fstype})
132 return nil
133 }
134
135
136 func (f *FakeMounter) Unmount(target string) error {
137 f.mutex.Lock()
138 defer f.mutex.Unlock()
139
140
141 absTarget, err := filepath.EvalSymlinks(target)
142 if err != nil {
143 absTarget = target
144 }
145
146 newMountpoints := []MountPoint{}
147 for _, mp := range f.MountPoints {
148 if mp.Path == absTarget {
149 if f.UnmountFunc != nil {
150 err := f.UnmountFunc(absTarget)
151 if err != nil {
152 return err
153 }
154 }
155 klog.V(5).Infof("Fake mounter: unmounted %s from %s", mp.Device, absTarget)
156
157 continue
158 }
159 newMountpoints = append(newMountpoints, MountPoint{Device: mp.Device, Path: mp.Path, Type: mp.Type})
160 }
161 f.MountPoints = newMountpoints
162 f.log = append(f.log, FakeAction{Action: FakeActionUnmount, Target: absTarget})
163 delete(f.MountCheckErrors, target)
164 return nil
165 }
166
167
168 func (f *FakeMounter) List() ([]MountPoint, error) {
169 f.mutex.Lock()
170 defer f.mutex.Unlock()
171
172 return f.MountPoints, nil
173 }
174
175
176
177 func (f *FakeMounter) IsLikelyNotMountPoint(file string) (bool, error) {
178 f.mutex.Lock()
179 defer f.mutex.Unlock()
180
181 err := f.MountCheckErrors[file]
182 if err != nil {
183 return false, err
184 }
185
186 _, err = os.Stat(file)
187 if err != nil {
188 return true, err
189 }
190
191
192 absFile, err := filepath.EvalSymlinks(file)
193 if err != nil {
194 absFile = file
195 }
196
197 for _, mp := range f.MountPoints {
198 if mp.Path == absFile {
199 klog.V(5).Infof("isLikelyNotMountPoint for %s: mounted %s, false", file, mp.Path)
200 return false, nil
201 }
202 }
203 klog.V(5).Infof("isLikelyNotMountPoint for %s: true", file)
204 return true, nil
205 }
206
207
208
209 func (f *FakeMounter) GetMountRefs(pathname string) ([]string, error) {
210 realpath, err := filepath.EvalSymlinks(pathname)
211 if err != nil {
212
213 realpath = pathname
214 }
215 return getMountRefsByDev(f, realpath)
216 }
217
View as plain text