@@ -2,24 +2,13 @@ package imagepullers
2
2
3
3
import (
4
4
"bufio"
5
- "errors"
6
5
"fmt"
7
6
"io"
8
7
"os"
9
- "os/exec"
10
- "path/filepath"
11
-
12
- "github.com/sirupsen/logrus"
13
8
14
9
"github.com/containers/podman/v5/pkg/machine/define"
15
10
16
11
"github.com/containers/podman/v5/pkg/machine/env"
17
-
18
- "github.com/lima-vm/go-qcow2reader"
19
- "github.com/lima-vm/go-qcow2reader/convert"
20
- "github.com/lima-vm/go-qcow2reader/image"
21
- "github.com/lima-vm/go-qcow2reader/image/qcow2"
22
- "github.com/lima-vm/go-qcow2reader/image/raw"
23
12
)
24
13
25
14
type NoopImagePuller struct {
@@ -40,21 +29,6 @@ func (puller *NoopImagePuller) SetSourceURI(sourcePath string) {
40
29
puller .sourceURI = sourcePath
41
30
}
42
31
43
- func imageExtension (vmType define.VMType , sourceURI string ) string {
44
- switch vmType {
45
- case define .WSLVirt :
46
- ext := filepath .Ext (sourceURI )
47
- if ext == ".wsl" {
48
- return ".wsl"
49
- }
50
- return ".tar.gz"
51
- case define .QemuVirt , define .HyperVVirt :
52
- return filepath .Ext (sourceURI )
53
- default :
54
- return "." + vmType .ImageFormat ().Kind ()
55
- }
56
- }
57
-
58
32
func (puller * NoopImagePuller ) LocalPath () (* define.VMFile , error ) {
59
33
// if localPath has already been calculated returns it
60
34
if puller .localPath != nil {
@@ -85,110 +59,14 @@ func (puller *NoopImagePuller) Download() error {
85
59
if err != nil {
86
60
return err
87
61
}
88
- return doCopyFile (puller .sourceURI , localPath .Path , puller .vmType )
89
- }
90
-
91
- func doCopyFile (src , dest string , vmType define.VMType ) error {
92
- srcF , err := os .Open (src )
93
- if err != nil {
94
- return err
95
- }
96
- defer srcF .Close ()
97
-
98
- switch vmType {
99
- case define .AppleHvVirt , define .LibKrun :
100
- return copyFileMac (srcF , dest )
101
- case define .WSLVirt , define .HyperVVirt :
102
- return copyFileWin (srcF , dest )
103
- default :
104
- return copyFile (srcF , dest )
105
- }
106
- }
107
-
108
- func copyFileMac (src * os.File , dest string ) error {
109
- srcImg , err := qcow2reader .Open (src )
110
- if err != nil {
111
- return err
112
- }
113
- defer srcImg .Close ()
114
-
115
- switch srcImg .Type () {
116
- case raw .Type :
117
- // if the image is raw it performs a simple copy
118
- return copyFile (src , dest )
119
- case qcow2 .Type :
120
- // if the image is qcow2 it performs a conversion to raw
121
- return convertToRaw (srcImg , dest )
122
- default :
123
- return fmt .Errorf ("%s format not supported for conversion to raw" , srcImg .Type ())
124
- }
125
- }
126
-
127
- func copyFileWin (srcF * os.File , dest string ) error {
128
- binary , err := exec .LookPath ("robocopy" )
129
- if err != nil {
130
- logrus .Debugf ("warning: failed to get robocopy binary: %v. Falling back to default file copy between %s and %s\n " , err , srcF .Name (), dest )
131
- return copyFile (srcF , dest )
132
- }
133
-
134
- srcDir , srcFile := filepath .Split (srcF .Name ())
135
- destDir := filepath .Dir (dest )
136
-
137
- // Executes the robocopy command with options optimized for a fast, single-file copy.
138
- // /J: Copies using unbuffered I/O (better for large files).
139
- // /MT: Enables multi-threaded copying for improved performance.
140
- // /R:0: Sets retries on failed copies to 0 to avoid long waits.
141
- // /IS: Includes Same files, which forces an overwrite even if the destination
142
- // file appears identical to the source.
143
- cmd := exec .Command (binary , "/J" , "/MT" , "/R:0" , "/IS" , srcDir , destDir , srcFile )
144
- if logrus .IsLevelEnabled (logrus .DebugLevel ) {
145
- cmd .Stdout = os .Stdout
146
- cmd .Stderr = os .Stderr
147
- } else {
148
- cmd .Stdout = io .Discard
149
- cmd .Stderr = io .Discard
150
- }
151
-
152
- err = cmd .Run ()
153
- if err != nil {
154
- // robocopy does not use classic exit codes like linux commands, so we need to check for specific errors
155
- // Only exit code 8 is considered an error, all other exit codes are considered successful with exceptions
156
- // see https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/robocopy
157
- var exitErr * exec.ExitError
158
- if errors .As (err , & exitErr ) {
159
- exitCode := exitErr .ExitCode ()
160
- if exitCode >= 8 {
161
- return fmt .Errorf ("failed to run robocopy: %w" , err )
162
- }
163
- } else {
164
- return fmt .Errorf ("failed to run robocopy: %w" , err )
165
- }
166
- }
167
-
168
- if err := os .Remove (dest ); err != nil && ! errors .Is (err , os .ErrNotExist ) {
169
- return fmt .Errorf ("failed to remove existing destination file: %w" , err )
170
- }
171
-
172
- err = os .Rename (filepath .Join (destDir , srcFile ), dest )
173
- if err != nil {
174
- return fmt .Errorf ("failed to rename file: %w" , err )
175
- }
176
-
177
- return nil
178
- }
179
62
180
- func convertToRaw (srcImg image.Image , dest string ) error {
181
- destF , err := os .Create (dest )
63
+ src , err := os .Open (puller .sourceURI )
182
64
if err != nil {
183
65
return err
184
66
}
185
- defer destF .Close ()
186
-
187
- if err := srcImg .Readable (); err != nil {
188
- return fmt .Errorf ("source image is not readable: %w" , err )
189
- }
67
+ defer src .Close ()
190
68
191
- return convert . Convert ( destF , srcImg , convert. Options {} )
69
+ return doCopyFile ( src , localPath . Path )
192
70
}
193
71
194
72
func copyFile (src * os.File , dest string ) error {
0 commit comments