1
16
17 package rbd
18
19 import (
20 "fmt"
21 "os"
22 "time"
23
24 "k8s.io/klog/v2"
25 "k8s.io/mount-utils"
26
27 v1 "k8s.io/api/core/v1"
28 "k8s.io/apimachinery/pkg/types"
29 "k8s.io/kubernetes/pkg/volume"
30 volutil "k8s.io/kubernetes/pkg/volume/util"
31 )
32
33
34 func (plugin *rbdPlugin) NewAttacher() (volume.Attacher, error) {
35 return plugin.newAttacherInternal(&rbdUtil{})
36 }
37
38
39 func (plugin *rbdPlugin) NewDeviceMounter() (volume.DeviceMounter, error) {
40 return plugin.NewAttacher()
41 }
42
43 func (plugin *rbdPlugin) newAttacherInternal(manager diskManager) (volume.Attacher, error) {
44 return &rbdAttacher{
45 plugin: plugin,
46 manager: manager,
47 mounter: volutil.NewSafeFormatAndMountFromHost(plugin.GetPluginName(), plugin.host),
48 }, nil
49 }
50
51
52 func (plugin *rbdPlugin) NewDetacher() (volume.Detacher, error) {
53 return plugin.newDetacherInternal(&rbdUtil{})
54 }
55
56
57 func (plugin *rbdPlugin) NewDeviceUnmounter() (volume.DeviceUnmounter, error) {
58 return plugin.NewDetacher()
59 }
60
61 func (plugin *rbdPlugin) newDetacherInternal(manager diskManager) (volume.Detacher, error) {
62 return &rbdDetacher{
63 plugin: plugin,
64 manager: manager,
65 mounter: volutil.NewSafeFormatAndMountFromHost(plugin.GetPluginName(), plugin.host),
66 }, nil
67 }
68
69
70 func (plugin *rbdPlugin) GetDeviceMountRefs(deviceMountPath string) ([]string, error) {
71 mounter := plugin.host.GetMounter(plugin.GetPluginName())
72 return mounter.GetMountRefs(deviceMountPath)
73 }
74
75 func (plugin *rbdPlugin) CanAttach(spec *volume.Spec) (bool, error) {
76 return true, nil
77 }
78
79 func (plugin *rbdPlugin) CanDeviceMount(spec *volume.Spec) (bool, error) {
80 return true, nil
81 }
82
83
84 type rbdAttacher struct {
85 plugin *rbdPlugin
86 mounter *mount.SafeFormatAndMount
87 manager diskManager
88 }
89
90 var _ volume.Attacher = &rbdAttacher{}
91
92 var _ volume.DeviceMounter = &rbdAttacher{}
93
94
95
96
97
98
99 func (attacher *rbdAttacher) Attach(spec *volume.Spec, nodeName types.NodeName) (string, error) {
100 return "", nil
101 }
102
103
104
105
106
107 func (attacher *rbdAttacher) VolumesAreAttached(specs []*volume.Spec, nodeName types.NodeName) (map[*volume.Spec]bool, error) {
108 volumesAttachedCheck := make(map[*volume.Spec]bool)
109 for _, spec := range specs {
110 volumesAttachedCheck[spec] = true
111 }
112 return volumesAttachedCheck, nil
113 }
114
115
116
117
118 func (attacher *rbdAttacher) WaitForAttach(spec *volume.Spec, devicePath string, pod *v1.Pod, timeout time.Duration) (string, error) {
119 klog.V(4).Infof("rbd: waiting for attach volume (name: %s) for pod (name: %s, uid: %s)", spec.Name(), pod.Name, pod.UID)
120 mounter, err := attacher.plugin.createMounterFromVolumeSpecAndPod(spec, pod)
121 if err != nil {
122 klog.Warningf("failed to create mounter: %v", spec)
123 return "", err
124 }
125 realDevicePath, err := attacher.manager.AttachDisk(*mounter)
126 if err != nil {
127 return "", err
128 }
129 klog.V(3).Infof("rbd: successfully wait for attach volume (spec: %s, pool: %s, image: %s) at %s", spec.Name(), mounter.Pool, mounter.Image, realDevicePath)
130 return realDevicePath, nil
131 }
132
133
134 func (attacher *rbdAttacher) GetDeviceMountPath(spec *volume.Spec) (string, error) {
135 img, err := getVolumeSourceImage(spec)
136 if err != nil {
137 return "", err
138 }
139 pool, err := getVolumeSourcePool(spec)
140 if err != nil {
141 return "", err
142 }
143 return makePDNameInternal(attacher.plugin.host, pool, img), nil
144 }
145
146
147
148
149 func (attacher *rbdAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMountPath string, mountArgs volume.DeviceMounterArgs) error {
150 klog.V(4).Infof("rbd: mouting device %s to %s", devicePath, deviceMountPath)
151 notMnt, err := attacher.mounter.IsLikelyNotMountPoint(deviceMountPath)
152 if err != nil {
153 if os.IsNotExist(err) {
154 if err := os.MkdirAll(deviceMountPath, 0750); err != nil {
155 return err
156 }
157 notMnt = true
158 } else {
159 return err
160 }
161 }
162 if !notMnt {
163 return nil
164 }
165 fstype, err := getVolumeSourceFSType(spec)
166 if err != nil {
167 return err
168 }
169 ro, err := getVolumeSourceReadOnly(spec)
170 if err != nil {
171 return err
172 }
173 options := []string{}
174 if ro {
175 options = append(options, "ro")
176 }
177 if mountArgs.SELinuxLabel != "" {
178 options = volutil.AddSELinuxMountOption(options, mountArgs.SELinuxLabel)
179 }
180 mountOptions := volutil.MountOptionFromSpec(spec, options...)
181
182 err = attacher.mounter.FormatAndMount(devicePath, deviceMountPath, fstype, mountOptions)
183 if err != nil {
184 os.Remove(deviceMountPath)
185 return fmt.Errorf("rbd: failed to mount device %s at %s (fstype: %s), error %v", devicePath, deviceMountPath, fstype, err)
186 }
187 klog.V(3).Infof("rbd: successfully mount device %s at %s (fstype: %s)", devicePath, deviceMountPath, fstype)
188 return nil
189 }
190
191
192 type rbdDetacher struct {
193 plugin *rbdPlugin
194 manager diskManager
195 mounter *mount.SafeFormatAndMount
196 }
197
198 var _ volume.Detacher = &rbdDetacher{}
199
200 var _ volume.DeviceUnmounter = &rbdDetacher{}
201
202
203
204
205
206
207
208
209
210
211
212
213 func (detacher *rbdDetacher) UnmountDevice(deviceMountPath string) error {
214 if pathExists, pathErr := mount.PathExists(deviceMountPath); pathErr != nil {
215 return fmt.Errorf("error checking if path exists: %v", pathErr)
216 } else if !pathExists {
217 klog.Warningf("Warning: Unmount skipped because path does not exist: %v", deviceMountPath)
218 return nil
219 }
220 devicePath, _, err := mount.GetDeviceNameFromMount(detacher.mounter, deviceMountPath)
221 if err != nil {
222 return err
223 }
224
225 notMnt, err := detacher.mounter.IsLikelyNotMountPoint(deviceMountPath)
226 if err != nil {
227 return err
228 }
229 if !notMnt {
230 klog.V(4).Infof("rbd: unmouting device mountpoint %s", deviceMountPath)
231 if err = detacher.mounter.Unmount(deviceMountPath); err != nil {
232 return err
233 }
234 klog.V(3).Infof("rbd: successfully unmount device mountpath %s", deviceMountPath)
235 }
236
237
238 if devicePath == "" {
239 rbdImageInfo, err := getRbdImageInfo(deviceMountPath)
240 if err != nil {
241 return err
242 }
243 found := false
244 devicePath, found = getRbdDevFromImageAndPool(rbdImageInfo.pool, rbdImageInfo.name)
245 if !found {
246 klog.Warningf("rbd: can't found devicePath for %v. Device is already unmounted, Image %v, Pool %v", deviceMountPath, rbdImageInfo.pool, rbdImageInfo.name)
247 }
248 }
249
250 if devicePath != "" {
251 klog.V(4).Infof("rbd: detaching device %s", devicePath)
252 err = detacher.manager.DetachDisk(detacher.plugin, deviceMountPath, devicePath)
253 if err != nil {
254 return err
255 }
256 klog.V(3).Infof("rbd: successfully detach device %s", devicePath)
257 }
258 err = os.Remove(deviceMountPath)
259 if err != nil {
260 return err
261 }
262 klog.V(3).Infof("rbd: successfully remove device mount point %s", deviceMountPath)
263 return nil
264 }
265
266
267 func (detacher *rbdDetacher) Detach(volumeName string, nodeName types.NodeName) error {
268 return nil
269 }
270
View as plain text