• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kubevirt / kubevirt / 7dc86bb8-0ab1-4cde-9ee6-3c44c6e610dd

19 Feb 2025 03:21AM UTC coverage: 71.633% (+0.02%) from 71.609%
7dc86bb8-0ab1-4cde-9ee6-3c44c6e610dd

push

prow

web-flow
Merge pull request #13807 from Barakmor1/diskinfo

Move disk info collection and verification from virt-handler to virt-launcher

54 of 110 new or added lines in 18 files covered. (49.09%)

9 existing lines in 3 files now uncovered.

62190 of 86818 relevant lines covered (71.63%)

0.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

30.75
/pkg/virt-handler/container-disk/mount.go
1
package container_disk
2

3
import (
4
        "errors"
5
        "fmt"
6
        "os"
7
        "path/filepath"
8
        "strings"
9
        "sync"
10
        "time"
11

12
        "kubevirt.io/kubevirt/pkg/checkpoint"
13
        "kubevirt.io/kubevirt/pkg/unsafepath"
14

15
        "kubevirt.io/kubevirt/pkg/safepath"
16
        "kubevirt.io/kubevirt/pkg/util"
17
        virtconfig "kubevirt.io/kubevirt/pkg/virt-config"
18
        virt_chroot "kubevirt.io/kubevirt/pkg/virt-handler/virt-chroot"
19

20
        "kubevirt.io/client-go/log"
21

22
        containerdisk "kubevirt.io/kubevirt/pkg/container-disk"
23
        "kubevirt.io/kubevirt/pkg/virt-handler/isolation"
24

25
        "k8s.io/apimachinery/pkg/api/equality"
26
        "k8s.io/apimachinery/pkg/types"
27

28
        v1 "kubevirt.io/api/core/v1"
29
)
30

31
const (
32
        failedCheckMountPointFmt = "failed to check mount point for containerDisk %v: %v"
33
        failedUnmountFmt         = "failed to unmount containerDisk %v: %v : %v"
34
)
35

36
var (
37
        ErrDiskContainerGone = errors.New("disk container is gone")
38
)
39

40
//go:generate mockgen -source $GOFILE -package=$GOPACKAGE -destination=generated_mock_$GOFILE
41

42
type mounter struct {
43
        podIsolationDetector       isolation.PodIsolationDetector
44
        checkpointManager          checkpoint.CheckpointManager
45
        mountRecords               map[types.UID]*vmiMountTargetRecord
46
        mountRecordsLock           sync.Mutex
47
        suppressWarningTimeout     time.Duration
48
        socketPathGetter           containerdisk.SocketPathGetter
49
        kernelBootSocketPathGetter containerdisk.KernelBootSocketPathGetter
50
        clusterConfig              *virtconfig.ClusterConfig
51
        nodeIsolationResult        isolation.IsolationResult
52
}
53

54
type Mounter interface {
55
        ContainerDisksReady(vmi *v1.VirtualMachineInstance, notInitializedSince time.Time) (bool, error)
56
        MountAndVerify(vmi *v1.VirtualMachineInstance) error
57
        Unmount(vmi *v1.VirtualMachineInstance) error
58
}
59

60
type vmiMountTargetEntry struct {
61
        TargetFile string `json:"targetFile"`
62
        SocketFile string `json:"socketFile"`
63
}
64

65
type vmiMountTargetRecord struct {
66
        MountTargetEntries []vmiMountTargetEntry `json:"mountTargetEntries"`
67
        UsesSafePaths      bool                  `json:"usesSafePaths"`
68
}
69

70
type kernelArtifacts struct {
71
        kernel *safepath.Path
72
        initrd *safepath.Path
73
}
74

75
func NewMounter(isoDetector isolation.PodIsolationDetector, mountStateDir string, clusterConfig *virtconfig.ClusterConfig) Mounter {
1✔
76
        return &mounter{
1✔
77
                mountRecords:               make(map[types.UID]*vmiMountTargetRecord),
1✔
78
                podIsolationDetector:       isoDetector,
1✔
79
                checkpointManager:          checkpoint.NewSimpleCheckpointManager(mountStateDir),
1✔
80
                suppressWarningTimeout:     1 * time.Minute,
1✔
81
                socketPathGetter:           containerdisk.NewSocketPathGetter(""),
1✔
82
                kernelBootSocketPathGetter: containerdisk.NewKernelBootSocketPathGetter(""),
1✔
83
                clusterConfig:              clusterConfig,
1✔
84
                nodeIsolationResult:        isolation.NodeIsolationResult(),
1✔
85
        }
1✔
86
}
1✔
87

88
func (m *mounter) deleteMountTargetRecord(vmi *v1.VirtualMachineInstance) error {
1✔
89
        if string(vmi.UID) == "" {
1✔
90
                return fmt.Errorf("unable to find container disk mounted directories for vmi without uid")
×
91
        }
×
92

93
        record := vmiMountTargetRecord{}
1✔
94
        err := m.checkpointManager.Get(string(vmi.UID), &record)
1✔
95
        if err != nil && !errors.Is(err, os.ErrNotExist) {
1✔
96
                return fmt.Errorf("failed to get a checkpoint %s, %w", vmi.UID, err)
×
97
        }
×
98
        if !errors.Is(err, os.ErrNotExist) {
2✔
99
                for _, target := range record.MountTargetEntries {
2✔
100
                        os.Remove(target.TargetFile)
1✔
101
                        os.Remove(target.SocketFile)
1✔
102
                }
1✔
103

104
                if err := m.checkpointManager.Delete(string(vmi.UID)); err != nil {
1✔
105
                        return fmt.Errorf("failed to delete checkpoint %s, %w", vmi.UID, err)
×
106
                }
×
107
        }
108

109
        m.mountRecordsLock.Lock()
1✔
110
        defer m.mountRecordsLock.Unlock()
1✔
111
        delete(m.mountRecords, vmi.UID)
1✔
112

1✔
113
        return nil
1✔
114
}
115

116
func (m *mounter) getMountTargetRecord(vmi *v1.VirtualMachineInstance) (*vmiMountTargetRecord, error) {
1✔
117
        var ok bool
1✔
118
        var existingRecord *vmiMountTargetRecord
1✔
119

1✔
120
        if string(vmi.UID) == "" {
1✔
121
                return nil, fmt.Errorf("unable to find container disk mounted directories for vmi without uid")
×
122
        }
×
123

124
        m.mountRecordsLock.Lock()
1✔
125
        defer m.mountRecordsLock.Unlock()
1✔
126
        existingRecord, ok = m.mountRecords[vmi.UID]
1✔
127

1✔
128
        // first check memory cache
1✔
129
        if ok {
2✔
130
                return existingRecord, nil
1✔
131
        }
1✔
132

133
        // if not there, see if record is on disk, this can happen if virt-handler restarts
134
        record := vmiMountTargetRecord{}
1✔
135
        err := m.checkpointManager.Get(string(vmi.UID), &record)
1✔
136
        if err != nil && !errors.Is(err, os.ErrNotExist) {
1✔
137
                return nil, fmt.Errorf("failed to get checkpoint %s, %w", vmi.UID, err)
×
138
        }
×
139

140
        if err == nil {
2✔
141
                // XXX: backward compatibility for old unresolved paths, can be removed in July 2023
1✔
142
                // After a one-time convert and persist, old records are safe too.
1✔
143
                if !record.UsesSafePaths {
1✔
144
                        record.UsesSafePaths = true
×
145
                        for i, entry := range record.MountTargetEntries {
×
146
                                safePath, err := safepath.JoinAndResolveWithRelativeRoot("/", entry.TargetFile)
×
147
                                if err != nil {
×
148
                                        return nil, fmt.Errorf("failed converting legacy path to safepath: %v", err)
×
149
                                }
×
150
                                record.MountTargetEntries[i].TargetFile = unsafepath.UnsafeAbsolute(safePath.Raw())
×
151
                        }
152
                }
153

154
                m.mountRecords[vmi.UID] = &record
1✔
155
                return &record, nil
1✔
156
        }
157

158
        // not found
159
        return nil, nil
1✔
160
}
161

162
func (m *mounter) addMountTargetRecord(vmi *v1.VirtualMachineInstance, record *vmiMountTargetRecord) error {
×
163
        return m.setAddMountTargetRecordHelper(vmi, record, true)
×
164
}
×
165

166
func (m *mounter) setMountTargetRecord(vmi *v1.VirtualMachineInstance, record *vmiMountTargetRecord) error {
1✔
167
        return m.setAddMountTargetRecordHelper(vmi, record, false)
1✔
168
}
1✔
169

170
func (m *mounter) setAddMountTargetRecordHelper(vmi *v1.VirtualMachineInstance, record *vmiMountTargetRecord, addPreviousRules bool) error {
1✔
171
        if string(vmi.UID) == "" {
1✔
172
                return fmt.Errorf("unable to set container disk mounted directories for vmi without uid")
×
173
        }
×
174
        // XXX: backward compatibility for old unresolved paths, can be removed in July 2023
175
        // After a one-time convert and persist, old records are safe too.
176
        record.UsesSafePaths = true
1✔
177

1✔
178
        err := m.checkpointManager.Get(string(vmi.UID), &vmiMountTargetRecord{})
1✔
179
        if err != nil && !errors.Is(err, os.ErrNotExist) {
1✔
180
                return fmt.Errorf("failed to get checkpoint %s, %w", vmi.UID, err)
×
181
        }
×
182

183
        m.mountRecordsLock.Lock()
1✔
184
        defer m.mountRecordsLock.Unlock()
1✔
185

1✔
186
        existingRecord, ok := m.mountRecords[vmi.UID]
1✔
187
        if ok && !errors.Is(err, os.ErrNotExist) && equality.Semantic.DeepEqual(existingRecord, record) {
1✔
188
                // already done
×
189
                return nil
×
190
        }
×
191

192
        if addPreviousRules && existingRecord != nil && len(existingRecord.MountTargetEntries) > 0 {
1✔
193
                record.MountTargetEntries = append(record.MountTargetEntries, existingRecord.MountTargetEntries...)
×
194
        }
×
195

196
        if err := m.checkpointManager.Store(string(vmi.UID), record); err != nil {
1✔
197
                return fmt.Errorf("failed to checkpoint %s, %w", vmi.UID, err)
×
198
        }
×
199

200
        m.mountRecords[vmi.UID] = record
1✔
201

1✔
202
        return nil
1✔
203
}
204

205
// Mount takes a vmi and mounts all container disks of the VMI, so that they are visible for the qemu process.
206
// Additionally qcow2 images are validated if "verify" is true. The validation happens with rlimits set, to avoid DOS.
207
func (m *mounter) MountAndVerify(vmi *v1.VirtualMachineInstance) error {
1✔
208
        record := vmiMountTargetRecord{}
1✔
209
        for i, volume := range vmi.Spec.Volumes {
1✔
UNCOV
210
                if volume.ContainerDisk != nil {
×
211
                        diskTargetDir, err := containerdisk.GetDiskTargetDirFromHostView(vmi)
×
212
                        if err != nil {
×
NEW
213
                                return err
×
214
                        }
×
215
                        diskName := containerdisk.GetDiskTargetName(i)
×
216
                        // If diskName is a symlink it will fail if the target exists.
×
217
                        if err := safepath.TouchAtNoFollow(diskTargetDir, diskName, os.ModePerm); err != nil {
×
218
                                if !os.IsExist(err) {
×
NEW
219
                                        return fmt.Errorf("failed to create mount point target: %v", err)
×
220
                                }
×
221
                        }
222
                        targetFile, err := safepath.JoinNoFollow(diskTargetDir, diskName)
×
223
                        if err != nil {
×
NEW
224
                                return err
×
225
                        }
×
226

227
                        sock, err := m.socketPathGetter(vmi, i)
×
228
                        if err != nil {
×
NEW
229
                                return err
×
230
                        }
×
231

232
                        record.MountTargetEntries = append(record.MountTargetEntries, vmiMountTargetEntry{
×
233
                                TargetFile: unsafepath.UnsafeAbsolute(targetFile.Raw()),
×
234
                                SocketFile: sock,
×
235
                        })
×
236
                }
237
        }
238

239
        if len(record.MountTargetEntries) > 0 {
1✔
240
                err := m.setMountTargetRecord(vmi, &record)
×
241
                if err != nil {
×
NEW
242
                        return err
×
243
                }
×
244
        }
245

246
        for i, volume := range vmi.Spec.Volumes {
1✔
UNCOV
247
                if volume.ContainerDisk != nil {
×
248
                        diskTargetDir, err := containerdisk.GetDiskTargetDirFromHostView(vmi)
×
249
                        if err != nil {
×
NEW
250
                                return err
×
251
                        }
×
252
                        diskName := containerdisk.GetDiskTargetName(i)
×
253
                        targetFile, err := safepath.JoinNoFollow(diskTargetDir, diskName)
×
254
                        if err != nil {
×
NEW
255
                                return err
×
256
                        }
×
257

258
                        if isMounted, err := isolation.IsMounted(targetFile); err != nil {
×
NEW
259
                                return fmt.Errorf("failed to determine if %s is already mounted: %v", targetFile, err)
×
260
                        } else if !isMounted {
×
261

×
262
                                sourceFile, err := m.getContainerDiskPath(vmi, &volume, i)
×
263
                                if err != nil {
×
NEW
264
                                        return fmt.Errorf("failed to find a sourceFile in containerDisk %v: %v", volume.Name, err)
×
265
                                }
×
266

267
                                log.DefaultLogger().Object(vmi).Infof("Bind mounting container disk at %s to %s", sourceFile, targetFile)
×
268
                                out, err := virt_chroot.MountChroot(sourceFile, targetFile, true).CombinedOutput()
×
269
                                if err != nil {
×
NEW
270
                                        return fmt.Errorf("failed to bindmount containerDisk %v: %v : %v", volume.Name, string(out), err)
×
271
                                }
×
272
                        }
273
                }
274
        }
275
        err := m.mountKernelArtifacts(vmi, true)
1✔
276
        if err != nil {
1✔
NEW
277
                return fmt.Errorf("error mounting kernel artifacts: %v", err)
×
278
        }
×
279

280
        return nil
1✔
281
}
282

283
// Unmount unmounts all container disks of a given VMI.
284
func (m *mounter) Unmount(vmi *v1.VirtualMachineInstance) error {
1✔
285
        if vmi.UID == "" {
2✔
286
                return nil
1✔
287
        }
1✔
288

289
        err := m.unmountKernelArtifacts(vmi)
1✔
290
        if err != nil {
1✔
291
                return fmt.Errorf("error unmounting kernel artifacts: %v", err)
×
292
        }
×
293

294
        record, err := m.getMountTargetRecord(vmi)
1✔
295
        if err != nil {
1✔
296
                return err
×
297
        } else if record == nil {
2✔
298
                // no entries to unmount
1✔
299

1✔
300
                log.DefaultLogger().Object(vmi).Infof("No container disk mount entries found to unmount")
1✔
301
                return nil
1✔
302
        }
1✔
303

304
        log.DefaultLogger().Object(vmi).Infof("Found container disk mount entries")
×
305
        for _, entry := range record.MountTargetEntries {
×
306
                log.DefaultLogger().Object(vmi).Infof("Looking to see if containerdisk is mounted at path %s", entry.TargetFile)
×
307
                file, err := safepath.NewFileNoFollow(entry.TargetFile)
×
308
                if err != nil {
×
309
                        if errors.Is(err, os.ErrNotExist) {
×
310
                                continue
×
311
                        }
312
                        return fmt.Errorf(failedCheckMountPointFmt, entry.TargetFile, err)
×
313
                }
314
                _ = file.Close()
×
315
                if mounted, err := isolation.IsMounted(file.Path()); err != nil {
×
316
                        return fmt.Errorf(failedCheckMountPointFmt, file, err)
×
317
                } else if mounted {
×
318
                        log.DefaultLogger().Object(vmi).Infof("unmounting container disk at path %s", file)
×
NEW
319
                        // #nosec No risk for attacker injection. Parameters are predefined strings
×
320
                        out, err := virt_chroot.UmountChroot(file.Path()).CombinedOutput()
×
321
                        if err != nil {
×
322
                                return fmt.Errorf(failedUnmountFmt, file, string(out), err)
×
323
                        }
×
324
                }
325
        }
326
        err = m.deleteMountTargetRecord(vmi)
×
327
        if err != nil {
×
328
                return err
×
329
        }
×
330

331
        return nil
×
332
}
333

334
func (m *mounter) ContainerDisksReady(vmi *v1.VirtualMachineInstance, notInitializedSince time.Time) (bool, error) {
1✔
335
        for i, volume := range vmi.Spec.Volumes {
2✔
336
                if volume.ContainerDisk != nil {
2✔
337
                        sock, err := m.socketPathGetter(vmi, i)
1✔
338
                        if err == nil {
2✔
339
                                _, err = m.podIsolationDetector.DetectForSocket(vmi, sock)
1✔
340
                        }
1✔
341

342
                        if err != nil {
2✔
343
                                log.DefaultLogger().Object(vmi).Reason(err).Infof("containerdisk %s not yet ready", volume.Name)
1✔
344
                                if time.Now().After(notInitializedSince.Add(m.suppressWarningTimeout)) {
2✔
345
                                        return false, fmt.Errorf("containerdisk %s still not ready after one minute", volume.Name)
1✔
346
                                }
1✔
347
                                return false, nil
1✔
348
                        }
349

350
                }
351
        }
352

353
        if util.HasKernelBootContainerImage(vmi) {
2✔
354
                sock, err := m.kernelBootSocketPathGetter(vmi)
1✔
355
                if err == nil {
2✔
356
                        _, err = m.podIsolationDetector.DetectForSocket(vmi, sock)
1✔
357
                }
1✔
358
                if err != nil {
2✔
359
                        log.DefaultLogger().Object(vmi).Reason(err).Info("kernelboot container not yet ready")
1✔
360
                        if time.Now().After(notInitializedSince.Add(m.suppressWarningTimeout)) {
2✔
361
                                return false, fmt.Errorf("kernelboot container still not ready after one minute")
1✔
362
                        }
1✔
363
                        return false, nil
1✔
364
                }
365
        }
366

367
        log.DefaultLogger().Object(vmi).V(4).Info("all containerdisks are ready")
1✔
368
        return true, nil
1✔
369
}
370

371
// MountKernelArtifacts mounts artifacts defined by KernelBootName in VMI.
372
// This function is assumed to run after MountAndVerify.
373
func (m *mounter) mountKernelArtifacts(vmi *v1.VirtualMachineInstance, verify bool) error {
1✔
374
        const kernelBootName = containerdisk.KernelBootName
1✔
375

1✔
376
        log.Log.Object(vmi).Infof("mounting kernel artifacts")
1✔
377

1✔
378
        if !util.HasKernelBootContainerImage(vmi) {
2✔
379
                log.Log.Object(vmi).Infof("kernel boot not defined - nothing to mount")
1✔
380
                return nil
1✔
381
        }
1✔
382

383
        kb := vmi.Spec.Domain.Firmware.KernelBoot.Container
×
384

×
385
        targetDir, err := containerdisk.GetDiskTargetDirFromHostView(vmi)
×
386
        if err != nil {
×
387
                return fmt.Errorf("failed to get disk target dir: %v", err)
×
388
        }
×
389
        if err := safepath.MkdirAtNoFollow(targetDir, containerdisk.KernelBootName, 0755); err != nil {
×
390
                if !os.IsExist(err) {
×
391
                        return err
×
392
                }
×
393
        }
394

395
        targetDir, err = safepath.JoinNoFollow(targetDir, containerdisk.KernelBootName)
×
396
        if err != nil {
×
397
                return err
×
398
        }
×
399
        if err := safepath.ChpermAtNoFollow(targetDir, 0, 0, 0755); err != nil {
×
400
                return err
×
401
        }
×
402

403
        socketFilePath, err := m.kernelBootSocketPathGetter(vmi)
×
404
        if err != nil {
×
405
                return fmt.Errorf("failed to find socket path for kernel artifacts: %v", err)
×
406
        }
×
407

408
        record := vmiMountTargetRecord{
×
409
                MountTargetEntries: []vmiMountTargetEntry{{
×
410
                        TargetFile: unsafepath.UnsafeAbsolute(targetDir.Raw()),
×
411
                        SocketFile: socketFilePath,
×
412
                }},
×
413
        }
×
414

×
415
        err = m.addMountTargetRecord(vmi, &record)
×
416
        if err != nil {
×
417
                return err
×
418
        }
×
419

420
        var targetInitrdPath *safepath.Path
×
421
        var targetKernelPath *safepath.Path
×
422

×
423
        if kb.InitrdPath != "" {
×
424
                if err := safepath.TouchAtNoFollow(targetDir, filepath.Base(kb.InitrdPath), 0655); err != nil && !os.IsExist(err) {
×
425
                        return err
×
426
                }
×
427

428
                targetInitrdPath, err = safepath.JoinNoFollow(targetDir, filepath.Base(kb.InitrdPath))
×
429
                if err != nil {
×
430
                        return err
×
431
                }
×
432
        }
433

434
        if kb.KernelPath != "" {
×
435
                if err := safepath.TouchAtNoFollow(targetDir, filepath.Base(kb.KernelPath), 0655); err != nil && !os.IsExist(err) {
×
436
                        return err
×
437
                }
×
438

439
                targetKernelPath, err = safepath.JoinNoFollow(targetDir, filepath.Base(kb.KernelPath))
×
440
                if err != nil {
×
441
                        return err
×
442
                }
×
443
        }
444

445
        areKernelArtifactsMounted := func(artifactsDir *safepath.Path, artifactFiles ...*safepath.Path) (bool, error) {
×
446
                if _, err = safepath.StatAtNoFollow(artifactsDir); errors.Is(err, os.ErrNotExist) {
×
447
                        return false, nil
×
448
                } else if err != nil {
×
449
                        return false, err
×
450
                }
×
451

452
                for _, mountPoint := range artifactFiles {
×
453
                        if mountPoint != nil {
×
454
                                isMounted, err := isolation.IsMounted(mountPoint)
×
455
                                if !isMounted || err != nil {
×
456
                                        return isMounted, err
×
457
                                }
×
458
                        }
459
                }
460
                return true, nil
×
461
        }
462

463
        if isMounted, err := areKernelArtifactsMounted(targetDir, targetInitrdPath, targetKernelPath); err != nil {
×
464
                return fmt.Errorf("failed to determine if %s is already mounted: %v", targetDir, err)
×
465
        } else if !isMounted {
×
466
                log.Log.Object(vmi).Infof("kernel artifacts are not mounted - mounting...")
×
467

×
468
                kernelArtifacts, err := m.getKernelArtifactPaths(vmi)
×
469
                if err != nil {
×
470
                        return err
×
471
                }
×
472

473
                if kernelArtifacts.kernel != nil {
×
474
                        out, err := virt_chroot.MountChroot(kernelArtifacts.kernel, targetKernelPath, true).CombinedOutput()
×
475
                        if err != nil {
×
476
                                return fmt.Errorf("failed to bindmount %v: %v : %v", kernelBootName, string(out), err)
×
477
                        }
×
478
                }
479

480
                if kernelArtifacts.initrd != nil {
×
481
                        out, err := virt_chroot.MountChroot(kernelArtifacts.initrd, targetInitrdPath, true).CombinedOutput()
×
482
                        if err != nil {
×
483
                                return fmt.Errorf("failed to bindmount %v: %v : %v", kernelBootName, string(out), err)
×
484
                        }
×
485
                }
486

487
        }
488

489
        if verify {
×
490
                mounted, err := areKernelArtifactsMounted(targetDir, targetInitrdPath, targetKernelPath)
×
491
                if err != nil {
×
492
                        return fmt.Errorf("failed to check if kernel artifacts are mounted. error: %v", err)
×
493
                } else if !mounted {
×
494
                        return fmt.Errorf("kernel artifacts verification failed")
×
495
                }
×
496
        }
497

498
        return nil
×
499
}
500

501
func (m *mounter) unmountKernelArtifacts(vmi *v1.VirtualMachineInstance) error {
1✔
502
        if !util.HasKernelBootContainerImage(vmi) {
2✔
503
                return nil
1✔
504
        }
1✔
505

506
        log.DefaultLogger().Object(vmi).Infof("unmounting kernel artifacts")
×
507

×
508
        kb := vmi.Spec.Domain.Firmware.KernelBoot.Container
×
509

×
510
        record, err := m.getMountTargetRecord(vmi)
×
511
        if err != nil {
×
512
                return fmt.Errorf("failed to get mount target record: %v", err)
×
513
        } else if record == nil {
×
514
                log.DefaultLogger().Object(vmi).Warning("Cannot find kernel-boot entries to unmount")
×
515
                return nil
×
516
        }
×
517

518
        unmount := func(targetDir *safepath.Path, artifactPaths ...string) error {
×
519
                for _, artifactPath := range artifactPaths {
×
520
                        if artifactPath == "" {
×
521
                                continue
×
522
                        }
523

524
                        targetPath, err := safepath.JoinNoFollow(targetDir, filepath.Base(artifactPath))
×
525
                        if err != nil {
×
526
                                return fmt.Errorf(failedCheckMountPointFmt, targetPath, err)
×
527
                        }
×
528
                        if mounted, err := isolation.IsMounted(targetPath); err != nil {
×
529
                                return fmt.Errorf(failedCheckMountPointFmt, targetPath, err)
×
530
                        } else if mounted {
×
531
                                log.DefaultLogger().Object(vmi).Infof("unmounting container disk at targetDir %s", targetPath)
×
532

×
533
                                out, err := virt_chroot.UmountChroot(targetPath).CombinedOutput()
×
534
                                if err != nil {
×
535
                                        return fmt.Errorf(failedUnmountFmt, targetPath, string(out), err)
×
536
                                }
×
537
                        }
538
                }
539
                return nil
×
540
        }
541

542
        for idx, entry := range record.MountTargetEntries {
×
543
                if !strings.Contains(entry.TargetFile, containerdisk.KernelBootName) {
×
544
                        continue
×
545
                }
546
                targetDir, err := safepath.NewFileNoFollow(entry.TargetFile)
×
547
                if err != nil {
×
548
                        return fmt.Errorf("failed to obtaining a reference to the target directory %q: %v", targetDir, err)
×
549
                }
×
550
                _ = targetDir.Close()
×
551
                log.DefaultLogger().Object(vmi).Infof("unmounting kernel artifacts in path: %v", targetDir)
×
552

×
553
                if err = unmount(targetDir.Path(), kb.InitrdPath, kb.KernelPath); err != nil {
×
554
                        // Not returning here since even if unmount wasn't successful it's better to keep
×
555
                        // cleaning the mounted files.
×
556
                        log.Log.Object(vmi).Reason(err).Error("unable to unmount kernel artifacts")
×
557
                }
×
558

559
                removeSliceElement := func(s []vmiMountTargetEntry, idxToRemove int) []vmiMountTargetEntry {
×
560
                        // removes slice element efficiently
×
561
                        s[idxToRemove] = s[len(s)-1]
×
562
                        return s[:len(s)-1]
×
563
                }
×
564

565
                record.MountTargetEntries = removeSliceElement(record.MountTargetEntries, idx)
×
566
                return nil
×
567
        }
568

569
        return fmt.Errorf("kernel artifacts record wasn't found")
×
570
}
571

572
func (m *mounter) getContainerDiskPath(vmi *v1.VirtualMachineInstance, volume *v1.Volume, volumeIndex int) (*safepath.Path, error) {
×
573
        sock, err := m.socketPathGetter(vmi, volumeIndex)
×
574
        if err != nil {
×
575
                return nil, ErrDiskContainerGone
×
576
        }
×
577

578
        res, err := m.podIsolationDetector.DetectForSocket(vmi, sock)
×
579
        if err != nil {
×
580
                return nil, fmt.Errorf("failed to detect socket for containerDisk %v: %v", volume.Name, err)
×
581
        }
×
582

583
        mountPoint, err := isolation.ParentPathForRootMount(m.nodeIsolationResult, res)
×
584
        if err != nil {
×
585
                return nil, fmt.Errorf("failed to detect root mount point of containerDisk %v on the node: %v", volume.Name, err)
×
586
        }
×
587

588
        return containerdisk.GetImage(mountPoint, volume.ContainerDisk.Path)
×
589
}
590

591
func (m *mounter) getKernelArtifactPaths(vmi *v1.VirtualMachineInstance) (*kernelArtifacts, error) {
×
592
        sock, err := m.kernelBootSocketPathGetter(vmi)
×
593
        if err != nil {
×
594
                return nil, ErrDiskContainerGone
×
595
        }
×
596

597
        res, err := m.podIsolationDetector.DetectForSocket(vmi, sock)
×
598
        if err != nil {
×
599
                return nil, fmt.Errorf("failed to detect socket for kernelboot container: %v", err)
×
600
        }
×
601

602
        mountPoint, err := isolation.ParentPathForRootMount(m.nodeIsolationResult, res)
×
603
        if err != nil {
×
604
                return nil, fmt.Errorf("failed to detect root mount point of kernel/initrd container on the node: %v", err)
×
605
        }
×
606

607
        kernelContainer := vmi.Spec.Domain.Firmware.KernelBoot.Container
×
608
        kernelArtifacts := &kernelArtifacts{}
×
609

×
610
        if kernelContainer.KernelPath != "" {
×
611
                kernelPath, err := containerdisk.GetImage(mountPoint, kernelContainer.KernelPath)
×
612
                if err != nil {
×
613
                        return nil, err
×
614
                }
×
615
                kernelArtifacts.kernel = kernelPath
×
616
        }
617
        if kernelContainer.InitrdPath != "" {
×
618
                initrdPath, err := containerdisk.GetImage(mountPoint, kernelContainer.InitrdPath)
×
619
                if err != nil {
×
620
                        return nil, err
×
621
                }
×
622
                kernelArtifacts.initrd = initrdPath
×
623
        }
624

625
        return kernelArtifacts, nil
×
626
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc