1
16
17 package iscsi
18
19 import (
20 "context"
21 "fmt"
22 "os"
23 "path/filepath"
24 "strconv"
25 "strings"
26
27 utilfeature "k8s.io/apiserver/pkg/util/feature"
28 "k8s.io/klog/v2"
29 "k8s.io/kubernetes/pkg/features"
30 "k8s.io/mount-utils"
31 utilexec "k8s.io/utils/exec"
32 "k8s.io/utils/io"
33 "k8s.io/utils/keymutex"
34 utilstrings "k8s.io/utils/strings"
35
36 v1 "k8s.io/api/core/v1"
37 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
38 "k8s.io/apimachinery/pkg/types"
39 "k8s.io/kubernetes/pkg/volume"
40 ioutil "k8s.io/kubernetes/pkg/volume/util"
41 "k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
42 )
43
44
45 func ProbeVolumePlugins() []volume.VolumePlugin {
46 return []volume.VolumePlugin{&iscsiPlugin{}}
47 }
48
49 type iscsiPlugin struct {
50 host volume.VolumeHost
51 targetLocks keymutex.KeyMutex
52 }
53
54 var _ volume.VolumePlugin = &iscsiPlugin{}
55 var _ volume.PersistentVolumePlugin = &iscsiPlugin{}
56 var _ volume.BlockVolumePlugin = &iscsiPlugin{}
57
58 const (
59 iscsiPluginName = "kubernetes.io/iscsi"
60 )
61
62 func (plugin *iscsiPlugin) Init(host volume.VolumeHost) error {
63 plugin.host = host
64 plugin.targetLocks = keymutex.NewHashed(0)
65 return nil
66 }
67
68 func (plugin *iscsiPlugin) GetPluginName() string {
69 return iscsiPluginName
70 }
71
72 func (plugin *iscsiPlugin) GetVolumeName(spec *volume.Spec) (string, error) {
73 tp, _, iqn, lun, err := getISCSITargetInfo(spec)
74 if err != nil {
75 return "", err
76 }
77
78 return fmt.Sprintf("%v:%v:%v", tp, iqn, lun), nil
79 }
80
81 func (plugin *iscsiPlugin) CanSupport(spec *volume.Spec) bool {
82 return (spec.Volume != nil && spec.Volume.ISCSI != nil) || (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.ISCSI != nil)
83 }
84
85 func (plugin *iscsiPlugin) RequiresRemount(spec *volume.Spec) bool {
86 return false
87 }
88
89 func (plugin *iscsiPlugin) SupportsMountOption() bool {
90 return true
91 }
92
93 func (plugin *iscsiPlugin) SupportsBulkVolumeVerification() bool {
94 return false
95 }
96
97 func (plugin *iscsiPlugin) SupportsSELinuxContextMount(spec *volume.Spec) (bool, error) {
98 return true, nil
99 }
100
101 func (plugin *iscsiPlugin) GetAccessModes() []v1.PersistentVolumeAccessMode {
102 return []v1.PersistentVolumeAccessMode{
103 v1.ReadWriteOnce,
104 v1.ReadOnlyMany,
105 }
106 }
107
108 func (plugin *iscsiPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.Mounter, error) {
109 if pod == nil {
110 return nil, fmt.Errorf("nil pod")
111 }
112 secret, err := createSecretMap(spec, plugin, pod.Namespace)
113 if err != nil {
114 return nil, err
115 }
116 return plugin.newMounterInternal(spec, pod.UID, &ISCSIUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()), secret)
117 }
118
119 func (plugin *iscsiPlugin) newMounterInternal(spec *volume.Spec, podUID types.UID, manager diskManager, mounter mount.Interface, exec utilexec.Interface, secret map[string]string) (volume.Mounter, error) {
120 readOnly, fsType, err := getISCSIVolumeInfo(spec)
121 if err != nil {
122 return nil, err
123 }
124 iscsiDisk, err := createISCSIDisk(spec, podUID, plugin, manager, secret)
125 if err != nil {
126 return nil, err
127 }
128
129 if iscsiDisk != nil {
130
131
132 iscsiDisk.MetricsProvider = volume.NewMetricsStatFS(iscsiDisk.GetPath())
133 }
134 return &iscsiDiskMounter{
135 iscsiDisk: iscsiDisk,
136 fsType: fsType,
137 readOnly: readOnly,
138 mounter: &mount.SafeFormatAndMount{Interface: mounter, Exec: exec},
139 exec: exec,
140 deviceUtil: ioutil.NewDeviceHandler(ioutil.NewIOHandler()),
141 mountOptions: ioutil.MountOptionFromSpec(spec),
142 }, nil
143 }
144
145
146 func (plugin *iscsiPlugin) NewBlockVolumeMapper(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.BlockVolumeMapper, error) {
147
148
149 var uid types.UID
150 var secret map[string]string
151 var err error
152 if pod != nil {
153 uid = pod.UID
154 secret, err = createSecretMap(spec, plugin, pod.Namespace)
155 if err != nil {
156 return nil, err
157 }
158 }
159 return plugin.newBlockVolumeMapperInternal(spec, uid, &ISCSIUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()), secret)
160 }
161
162 func (plugin *iscsiPlugin) newBlockVolumeMapperInternal(spec *volume.Spec, podUID types.UID, manager diskManager, mounter mount.Interface, exec utilexec.Interface, secret map[string]string) (volume.BlockVolumeMapper, error) {
163 readOnly, _, err := getISCSIVolumeInfo(spec)
164 if err != nil {
165 return nil, err
166 }
167 iscsiDisk, err := createISCSIDisk(spec, podUID, plugin, manager, secret)
168 if err != nil {
169 return nil, err
170 }
171 mapper := &iscsiDiskMapper{
172 iscsiDisk: iscsiDisk,
173 readOnly: readOnly,
174 exec: exec,
175 deviceUtil: ioutil.NewDeviceHandler(ioutil.NewIOHandler()),
176 }
177
178 blockPath, err := mapper.GetGlobalMapPath(spec)
179 if err != nil {
180 return nil, fmt.Errorf("failed to get device path: %v", err)
181 }
182 mapper.MetricsProvider = volume.NewMetricsBlock(filepath.Join(blockPath, string(podUID)))
183
184 return mapper, nil
185 }
186
187 func (plugin *iscsiPlugin) NewUnmounter(volName string, podUID types.UID) (volume.Unmounter, error) {
188 return plugin.newUnmounterInternal(volName, podUID, &ISCSIUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
189 }
190
191 func (plugin *iscsiPlugin) newUnmounterInternal(volName string, podUID types.UID, manager diskManager, mounter mount.Interface, exec utilexec.Interface) (volume.Unmounter, error) {
192 return &iscsiDiskUnmounter{
193 iscsiDisk: &iscsiDisk{
194 podUID: podUID,
195 VolName: volName,
196 manager: manager,
197 plugin: plugin,
198 MetricsProvider: volume.NewMetricsStatFS(plugin.host.GetPodVolumeDir(podUID, utilstrings.EscapeQualifiedName(iscsiPluginName), volName)),
199 },
200 mounter: mounter,
201 exec: exec,
202 deviceUtil: ioutil.NewDeviceHandler(ioutil.NewIOHandler()),
203 }, nil
204 }
205
206
207 func (plugin *iscsiPlugin) NewBlockVolumeUnmapper(volName string, podUID types.UID) (volume.BlockVolumeUnmapper, error) {
208 return plugin.newUnmapperInternal(volName, podUID, &ISCSIUtil{}, plugin.host.GetExec(plugin.GetPluginName()))
209 }
210
211 func (plugin *iscsiPlugin) newUnmapperInternal(volName string, podUID types.UID, manager diskManager, exec utilexec.Interface) (volume.BlockVolumeUnmapper, error) {
212 return &iscsiDiskUnmapper{
213 iscsiDisk: &iscsiDisk{
214 podUID: podUID,
215 VolName: volName,
216 manager: manager,
217 plugin: plugin,
218 },
219 exec: exec,
220 deviceUtil: ioutil.NewDeviceHandler(ioutil.NewIOHandler()),
221 }, nil
222 }
223
224 func (plugin *iscsiPlugin) ConstructVolumeSpec(volumeName, mountPath string) (volume.ReconstructedVolume, error) {
225
226 var globalPDPath string
227 mounter := plugin.host.GetMounter(plugin.GetPluginName())
228
229
230
231
232 paths, err := ioutil.GetReliableMountRefs(mounter, mountPath)
233 if io.IsInconsistentReadError(err) {
234 klog.Errorf("Failed to read mount refs from /proc/mounts for %s: %s", mountPath, err)
235 klog.Errorf("Kubelet cannot unmount volume at %s, please unmount it and all mounts of the same device manually.", mountPath)
236 return volume.ReconstructedVolume{}, err
237 }
238 if err != nil {
239 return volume.ReconstructedVolume{}, err
240 }
241
242 for _, path := range paths {
243 if strings.Contains(path, plugin.host.GetPluginDir(iscsiPluginName)) {
244 globalPDPath = path
245 break
246 }
247 }
248
249 if len(globalPDPath) == 0 {
250 return volume.ReconstructedVolume{}, fmt.Errorf("couldn't fetch globalPDPath. failed to obtain volume spec")
251 }
252
253
254 device, _, err := extractDeviceAndPrefix(globalPDPath)
255 if err != nil {
256 return volume.ReconstructedVolume{}, err
257 }
258 bkpPortal, iqn, err := extractPortalAndIqn(device)
259 if err != nil {
260 return volume.ReconstructedVolume{}, err
261 }
262 arr := strings.Split(device, "-lun-")
263 if len(arr) < 2 {
264 return volume.ReconstructedVolume{}, fmt.Errorf("failed to retrieve lun from globalPDPath: %v", globalPDPath)
265 }
266 lun, err := strconv.Atoi(arr[1])
267 if err != nil {
268 return volume.ReconstructedVolume{}, err
269 }
270 iface, _ := extractIface(globalPDPath)
271 iscsiVolume := &v1.Volume{
272 Name: volumeName,
273 VolumeSource: v1.VolumeSource{
274 ISCSI: &v1.ISCSIVolumeSource{
275 TargetPortal: bkpPortal,
276 IQN: iqn,
277 Lun: int32(lun),
278 ISCSIInterface: iface,
279 },
280 },
281 }
282
283 var mountContext string
284 if utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
285 kvh, ok := plugin.host.(volume.KubeletVolumeHost)
286 if !ok {
287 return volume.ReconstructedVolume{}, fmt.Errorf("plugin volume host does not implement KubeletVolumeHost interface")
288 }
289 hu := kvh.GetHostUtil()
290 mountContext, err = hu.GetSELinuxMountContext(mountPath)
291 if err != nil {
292 return volume.ReconstructedVolume{}, err
293 }
294 }
295
296 return volume.ReconstructedVolume{
297 Spec: volume.NewSpecFromVolume(iscsiVolume),
298 SELinuxMountContext: mountContext,
299 }, nil
300 }
301
302 func (plugin *iscsiPlugin) ConstructBlockVolumeSpec(podUID types.UID, volumeName, mapPath string) (*volume.Spec, error) {
303 pluginDir := plugin.host.GetVolumeDevicePluginDir(iscsiPluginName)
304 blkutil := volumepathhandler.NewBlockVolumePathHandler()
305 globalMapPathUUID, err := blkutil.FindGlobalMapPathUUIDFromPod(pluginDir, mapPath, podUID)
306 if err != nil {
307 return nil, err
308 }
309 klog.V(5).Infof("globalMapPathUUID: %v, err: %v", globalMapPathUUID, err)
310
311
312
313
314 globalMapPath := filepath.Dir(globalMapPathUUID)
315 return getVolumeSpecFromGlobalMapPath(volumeName, globalMapPath)
316 }
317
318 type iscsiDisk struct {
319 VolName string
320 podUID types.UID
321 Portals []string
322 Iqn string
323 Lun string
324 InitIface string
325 Iface string
326 chapDiscovery bool
327 chapSession bool
328 secret map[string]string `datapolicy:"token"`
329 InitiatorName string
330 plugin *iscsiPlugin
331
332 manager diskManager
333 volume.MetricsProvider
334 }
335
336 func (iscsi *iscsiDisk) GetPath() string {
337 name := iscsiPluginName
338
339 return iscsi.plugin.host.GetPodVolumeDir(iscsi.podUID, utilstrings.EscapeQualifiedName(name), iscsi.VolName)
340 }
341
342 func (iscsi *iscsiDisk) iscsiGlobalMapPath(spec *volume.Spec) (string, error) {
343 mounter, err := volumeSpecToMounter(spec, iscsi.plugin.host, iscsi.plugin.targetLocks, nil )
344 if err != nil {
345 klog.Warningf("failed to get iscsi mounter: %v", err)
346 return "", err
347 }
348 return iscsi.manager.MakeGlobalVDPDName(*mounter.iscsiDisk), nil
349 }
350
351 func (iscsi *iscsiDisk) iscsiPodDeviceMapPath() (string, string) {
352 name := iscsiPluginName
353 return iscsi.plugin.host.GetPodVolumeDeviceDir(iscsi.podUID, utilstrings.EscapeQualifiedName(name)), iscsi.VolName
354 }
355
356 type iscsiDiskMounter struct {
357 *iscsiDisk
358 readOnly bool
359 fsType string
360 volumeMode v1.PersistentVolumeMode
361 mounter *mount.SafeFormatAndMount
362 exec utilexec.Interface
363 deviceUtil ioutil.DeviceUtil
364 mountOptions []string
365 mountedWithSELinuxContext bool
366 }
367
368 var _ volume.Mounter = &iscsiDiskMounter{}
369
370 func (b *iscsiDiskMounter) GetAttributes() volume.Attributes {
371 return volume.Attributes{
372 ReadOnly: b.readOnly,
373 Managed: !b.readOnly,
374 SELinuxRelabel: !b.mountedWithSELinuxContext,
375 }
376 }
377
378 func (b *iscsiDiskMounter) SetUp(mounterArgs volume.MounterArgs) error {
379 return b.SetUpAt(b.GetPath(), mounterArgs)
380 }
381
382 func (b *iscsiDiskMounter) SetUpAt(dir string, mounterArgs volume.MounterArgs) error {
383
384 err := diskSetUp(b.manager, *b, dir, b.mounter, mounterArgs.FsGroup, mounterArgs.FSGroupChangePolicy)
385 if err != nil {
386 klog.Errorf("iscsi: failed to setup")
387 }
388
389 if utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
390
391
392 b.mountedWithSELinuxContext = mounterArgs.SELinuxLabel != ""
393 }
394 return err
395 }
396
397 type iscsiDiskUnmounter struct {
398 *iscsiDisk
399 mounter mount.Interface
400 exec utilexec.Interface
401 deviceUtil ioutil.DeviceUtil
402 }
403
404 var _ volume.Unmounter = &iscsiDiskUnmounter{}
405
406
407
408 func (c *iscsiDiskUnmounter) TearDown() error {
409 return c.TearDownAt(c.GetPath())
410 }
411
412 func (c *iscsiDiskUnmounter) TearDownAt(dir string) error {
413 return mount.CleanupMountPoint(dir, c.mounter, false)
414 }
415
416
417 type iscsiDiskMapper struct {
418 *iscsiDisk
419 readOnly bool
420 exec utilexec.Interface
421 deviceUtil ioutil.DeviceUtil
422 }
423
424 var _ volume.BlockVolumeMapper = &iscsiDiskMapper{}
425
426 type iscsiDiskUnmapper struct {
427 *iscsiDisk
428 exec utilexec.Interface
429 deviceUtil ioutil.DeviceUtil
430 volume.MetricsNil
431 }
432
433
434
435 func (idm *iscsiDiskMapper) SupportsMetrics() bool {
436 return true
437 }
438
439 var _ volume.BlockVolumeUnmapper = &iscsiDiskUnmapper{}
440 var _ volume.CustomBlockVolumeUnmapper = &iscsiDiskUnmapper{}
441
442
443
444
445 func (c *iscsiDiskUnmapper) TearDownDevice(mapPath, _ string) error {
446 err := c.manager.DetachBlockISCSIDisk(*c, mapPath)
447 if err != nil {
448 return fmt.Errorf("iscsi: failed to detach disk: %s\nError: %v", mapPath, err)
449 }
450 klog.V(4).Infof("iscsi: %q is unmounted, deleting the directory", mapPath)
451 err = os.RemoveAll(mapPath)
452 if err != nil {
453 return fmt.Errorf("iscsi: failed to delete the directory: %s\nError: %v", mapPath, err)
454 }
455 klog.V(4).Infof("iscsi: successfully detached disk: %s", mapPath)
456 return nil
457 }
458
459 func (c *iscsiDiskUnmapper) UnmapPodDevice() error {
460 return nil
461 }
462
463
464
465 func (iscsi *iscsiDisk) GetGlobalMapPath(spec *volume.Spec) (string, error) {
466 return iscsi.iscsiGlobalMapPath(spec)
467 }
468
469
470
471
472 func (iscsi *iscsiDisk) GetPodDeviceMapPath() (string, string) {
473 return iscsi.iscsiPodDeviceMapPath()
474 }
475
476 func portalMounter(portal string) string {
477 if !strings.Contains(portal, ":") {
478 portal = portal + ":3260"
479 }
480 return portal
481 }
482
483
484 func getISCSIVolumeInfo(spec *volume.Spec) (bool, string, error) {
485
486
487 if spec.Volume != nil && spec.Volume.ISCSI != nil {
488 return spec.Volume.ISCSI.ReadOnly, spec.Volume.ISCSI.FSType, nil
489 } else if spec.PersistentVolume != nil &&
490 spec.PersistentVolume.Spec.ISCSI != nil {
491 return spec.ReadOnly, spec.PersistentVolume.Spec.ISCSI.FSType, nil
492 }
493
494 return false, "", fmt.Errorf("Spec does not reference an ISCSI volume type")
495 }
496
497
498 func getISCSITargetInfo(spec *volume.Spec) (string, []string, string, int32, error) {
499 if spec.Volume != nil && spec.Volume.ISCSI != nil {
500 return spec.Volume.ISCSI.TargetPortal, spec.Volume.ISCSI.Portals, spec.Volume.ISCSI.IQN, spec.Volume.ISCSI.Lun, nil
501 } else if spec.PersistentVolume != nil &&
502 spec.PersistentVolume.Spec.ISCSI != nil {
503 return spec.PersistentVolume.Spec.ISCSI.TargetPortal, spec.PersistentVolume.Spec.ISCSI.Portals, spec.PersistentVolume.Spec.ISCSI.IQN, spec.PersistentVolume.Spec.ISCSI.Lun, nil
504 }
505
506 return "", nil, "", 0, fmt.Errorf("Spec does not reference an ISCSI volume type")
507 }
508
509
510 func getISCSIInitiatorInfo(spec *volume.Spec) (string, *string, error) {
511 if spec.Volume != nil && spec.Volume.ISCSI != nil {
512 return spec.Volume.ISCSI.ISCSIInterface, spec.Volume.ISCSI.InitiatorName, nil
513 } else if spec.PersistentVolume != nil &&
514 spec.PersistentVolume.Spec.ISCSI != nil {
515 return spec.PersistentVolume.Spec.ISCSI.ISCSIInterface, spec.PersistentVolume.Spec.ISCSI.InitiatorName, nil
516 }
517
518 return "", nil, fmt.Errorf("Spec does not reference an ISCSI volume type")
519 }
520
521
522 func getISCSIDiscoveryCHAPInfo(spec *volume.Spec) (bool, error) {
523 if spec.Volume != nil && spec.Volume.ISCSI != nil {
524 return spec.Volume.ISCSI.DiscoveryCHAPAuth, nil
525 } else if spec.PersistentVolume != nil &&
526 spec.PersistentVolume.Spec.ISCSI != nil {
527 return spec.PersistentVolume.Spec.ISCSI.DiscoveryCHAPAuth, nil
528 }
529
530 return false, fmt.Errorf("Spec does not reference an ISCSI volume type")
531 }
532
533
534 func getISCSISessionCHAPInfo(spec *volume.Spec) (bool, error) {
535 if spec.Volume != nil && spec.Volume.ISCSI != nil {
536 return spec.Volume.ISCSI.SessionCHAPAuth, nil
537 } else if spec.PersistentVolume != nil &&
538 spec.PersistentVolume.Spec.ISCSI != nil {
539 return spec.PersistentVolume.Spec.ISCSI.SessionCHAPAuth, nil
540 }
541
542 return false, fmt.Errorf("Spec does not reference an ISCSI volume type")
543 }
544
545
546 func getISCSISecretNameAndNamespace(spec *volume.Spec, defaultSecretNamespace string) (string, string, error) {
547 if spec.Volume != nil && spec.Volume.ISCSI != nil {
548 if spec.Volume.ISCSI.SecretRef != nil {
549 return spec.Volume.ISCSI.SecretRef.Name, defaultSecretNamespace, nil
550 }
551 return "", "", nil
552 } else if spec.PersistentVolume != nil &&
553 spec.PersistentVolume.Spec.ISCSI != nil {
554 secretRef := spec.PersistentVolume.Spec.ISCSI.SecretRef
555 secretNs := defaultSecretNamespace
556 if secretRef != nil {
557 if len(secretRef.Namespace) != 0 {
558 secretNs = secretRef.Namespace
559 }
560 return secretRef.Name, secretNs, nil
561 }
562 return "", "", nil
563 }
564
565 return "", "", fmt.Errorf("Spec does not reference an ISCSI volume type")
566 }
567
568 func createISCSIDisk(spec *volume.Spec, podUID types.UID, plugin *iscsiPlugin, manager diskManager, secret map[string]string) (*iscsiDisk, error) {
569 tp, portals, iqn, lunStr, err := getISCSITargetInfo(spec)
570 if err != nil {
571 return nil, err
572 }
573
574 lun := strconv.Itoa(int(lunStr))
575 portal := portalMounter(tp)
576 var bkportal []string
577 bkportal = append(bkportal, portal)
578 for _, p := range portals {
579 bkportal = append(bkportal, portalMounter(string(p)))
580 }
581
582 iface, initiatorNamePtr, err := getISCSIInitiatorInfo(spec)
583 if err != nil {
584 return nil, err
585 }
586
587 var initiatorName string
588 if initiatorNamePtr != nil {
589 initiatorName = *initiatorNamePtr
590 }
591 chapDiscovery, err := getISCSIDiscoveryCHAPInfo(spec)
592 if err != nil {
593 return nil, err
594 }
595 chapSession, err := getISCSISessionCHAPInfo(spec)
596 if err != nil {
597 return nil, err
598 }
599
600 initIface := iface
601 if initiatorName != "" {
602 iface = bkportal[0] + ":" + spec.Name()
603 }
604
605 return &iscsiDisk{
606 podUID: podUID,
607 VolName: spec.Name(),
608 Portals: bkportal,
609 Iqn: iqn,
610 Lun: lun,
611 InitIface: initIface,
612 Iface: iface,
613 chapDiscovery: chapDiscovery,
614 chapSession: chapSession,
615 secret: secret,
616 InitiatorName: initiatorName,
617 manager: manager,
618 plugin: plugin}, nil
619 }
620
621 func createSecretMap(spec *volume.Spec, plugin *iscsiPlugin, namespace string) (map[string]string, error) {
622 var secret map[string]string
623 chapDiscover, err := getISCSIDiscoveryCHAPInfo(spec)
624 if err != nil {
625 return nil, err
626 }
627 chapSession, err := getISCSISessionCHAPInfo(spec)
628 if err != nil {
629 return nil, err
630 }
631 if chapDiscover || chapSession {
632 secretName, secretNamespace, err := getISCSISecretNameAndNamespace(spec, namespace)
633 if err != nil {
634 return nil, err
635 }
636
637 if len(secretName) > 0 && len(secretNamespace) > 0 {
638
639 kubeClient := plugin.host.GetKubeClient()
640 if kubeClient == nil {
641 return nil, fmt.Errorf("cannot get kube client")
642 }
643 secretObj, err := kubeClient.CoreV1().Secrets(secretNamespace).Get(context.TODO(), secretName, metav1.GetOptions{})
644 if err != nil {
645 err = fmt.Errorf("couldn't get secret %v/%v error: %w", secretNamespace, secretName, err)
646 return nil, err
647 }
648 secret = make(map[string]string)
649 for name, data := range secretObj.Data {
650 klog.V(4).Infof("retrieving CHAP secret name: %s", name)
651 secret[name] = string(data)
652 }
653 }
654 }
655 return secret, err
656 }
657
658 func createPersistentVolumeFromISCSIPVSource(volumeName string, iscsi v1.ISCSIPersistentVolumeSource) *v1.PersistentVolume {
659 block := v1.PersistentVolumeBlock
660 return &v1.PersistentVolume{
661 ObjectMeta: metav1.ObjectMeta{
662 Name: volumeName,
663 },
664 Spec: v1.PersistentVolumeSpec{
665 PersistentVolumeSource: v1.PersistentVolumeSource{
666 ISCSI: &iscsi,
667 },
668 VolumeMode: &block,
669 },
670 }
671 }
672
673 func getVolumeSpecFromGlobalMapPath(volumeName, globalMapPath string) (*volume.Spec, error) {
674
675
676
677
678
679
680 device, _, err := extractDeviceAndPrefix(globalMapPath)
681 if err != nil {
682 return nil, err
683 }
684 bkpPortal, iqn, err := extractPortalAndIqn(device)
685 if err != nil {
686 return nil, err
687 }
688 arr := strings.Split(device, "-lun-")
689 if len(arr) < 2 {
690 return nil, fmt.Errorf("failed to retrieve lun from globalMapPath: %v", globalMapPath)
691 }
692 lun, err := strconv.Atoi(arr[1])
693 if err != nil {
694 return nil, err
695 }
696 iface, found := extractIface(globalMapPath)
697 if !found {
698 return nil, fmt.Errorf("failed to retrieve iface from globalMapPath: %v", globalMapPath)
699 }
700 iscsiPV := createPersistentVolumeFromISCSIPVSource(volumeName,
701 v1.ISCSIPersistentVolumeSource{
702 TargetPortal: bkpPortal,
703 IQN: iqn,
704 Lun: int32(lun),
705 ISCSIInterface: iface,
706 },
707 )
708 klog.V(5).Infof("ConstructBlockVolumeSpec: TargetPortal: %v, IQN: %v, Lun: %v, ISCSIInterface: %v",
709 iscsiPV.Spec.PersistentVolumeSource.ISCSI.TargetPortal,
710 iscsiPV.Spec.PersistentVolumeSource.ISCSI.IQN,
711 iscsiPV.Spec.PersistentVolumeSource.ISCSI.Lun,
712 iscsiPV.Spec.PersistentVolumeSource.ISCSI.ISCSIInterface,
713 )
714 return volume.NewSpecFromPersistentVolume(iscsiPV, false), nil
715 }
716
View as plain text