@@ -13,6 +13,7 @@ import (
1313 "strings"
1414
1515 "github.com/containers/podman/v5/pkg/bindings"
16+ "github.com/containers/podman/v5/pkg/domain/entities"
1617 "github.com/containers/podman/v5/pkg/machine/define"
1718 "github.com/containers/podman/v5/pkg/machine/env"
1819 "github.com/containers/podman/v5/pkg/machine/provider"
@@ -25,44 +26,46 @@ import (
2526// FindMachineByPort finds a running machine that matches the given connection port.
2627// It returns the machine configuration and provider, or an error if not found.
2728func FindMachineByPort (connectionURI string , parsedConnection * url.URL ) (* vmconfigs.MachineConfig , vmconfigs.VMProvider , error ) {
28- machineProvider , err := provider .Get ()
29- if err != nil {
30- return nil , nil , fmt .Errorf ("getting machine provider: %w" , err )
31- }
32-
33- dirs , err := env .GetMachineDirs (machineProvider .VMType ())
34- if err != nil {
35- return nil , nil , err
36- }
37-
38- machineList , err := vmconfigs .LoadMachinesInDir (dirs )
39- if err != nil {
40- return nil , nil , fmt .Errorf ("listing machines: %w" , err )
41- }
42-
43- // Now we know that the connection points to a machine and we
44- // can find the machine by looking for the one with the
45- // matching port.
46- connectionPort , err := strconv .Atoi (parsedConnection .Port ())
47- if err != nil {
48- return nil , nil , fmt .Errorf ("parsing connection port: %w" , err )
49- }
50-
51- for _ , mc := range machineList {
52- if connectionPort != mc .SSH .Port {
29+ for _ , machineProvider := range provider .GetAll () {
30+ logrus .Debugf ("Checking provider: %s" , machineProvider .VMType ())
31+ dirs , err := env .GetMachineDirs (machineProvider .VMType ())
32+ if err != nil {
33+ logrus .Debugf ("Failed to get machine dirs for provider %s: %v" , machineProvider .VMType (), err )
5334 continue
5435 }
5536
56- state , err := machineProvider . State ( mc , false )
37+ machineList , err := vmconfigs . LoadMachinesInDir ( dirs )
5738 if err != nil {
58- return nil , nil , err
39+ logrus .Debugf ("Failed to list machines: %v" , err )
40+ continue
5941 }
6042
61- if state != define .Running {
62- return nil , nil , fmt .Errorf ("machine %s is not running but in state %s" , mc .Name , state )
43+ // Now we know that the connection points to a machine and we
44+ // can find the machine by looking for the one with the
45+ // matching port.
46+ connectionPort , err := strconv .Atoi (parsedConnection .Port ())
47+ if err != nil {
48+ logrus .Debugf ("Failed to parse connection port: %v" , err )
49+ continue
6350 }
6451
65- return mc , machineProvider , nil
52+ for _ , mc := range machineList {
53+ if connectionPort != mc .SSH .Port {
54+ continue
55+ }
56+
57+ state , err := machineProvider .State (mc , false )
58+ if err != nil {
59+ logrus .Debugf ("Failed to get machine state for %s: %v" , mc .Name , err )
60+ continue
61+ }
62+
63+ if state != define .Running {
64+ return nil , nil , fmt .Errorf ("machine %s is not running but in state %s" , mc .Name , state )
65+ }
66+
67+ return mc , machineProvider , nil
68+ }
6669 }
6770
6871 return nil , nil , fmt .Errorf ("could not find a matching machine for connection %q" , connectionURI )
@@ -154,3 +157,113 @@ func CheckPathOnRunningMachine(ctx context.Context, path string) (*LocalAPIMap,
154157
155158 return isPathAvailableOnMachine (mounts , vmType , path )
156159}
160+
161+ // CheckIfImageBuildPathsOnRunningMachine checks if the build context directory and all specified
162+ // Containerfiles are available on the running machine. If they are, it translates their paths
163+ // to the corresponding remote paths and returns them along with a flag indicating success.
164+ func CheckIfImageBuildPathsOnRunningMachine (ctx context.Context , containerFiles []string , options entities.BuildOptions ) ([]string , entities.BuildOptions , bool ) {
165+ if machineMode := bindings .GetMachineMode (ctx ); ! machineMode {
166+ logrus .Debug ("Machine mode is not enabled, skipping machine check" )
167+ return nil , options , false
168+ }
169+
170+ conn , err := bindings .GetClient (ctx )
171+ if err != nil {
172+ logrus .Debugf ("Failed to get client connection: %v" , err )
173+ return nil , options , false
174+ }
175+
176+ mounts , vmType , err := getMachineMountsAndVMType (conn .URI .String (), conn .URI )
177+ if err != nil {
178+ logrus .Debugf ("Failed to get machine mounts: %v" , err )
179+ return nil , options , false
180+ }
181+
182+ // Context directory
183+ if err := fileutils .Lexists (options .ContextDirectory ); errors .Is (err , fs .ErrNotExist ) {
184+ logrus .Debugf ("Path %s does not exist locally, skipping machine check" , options .ContextDirectory )
185+ return nil , options , false
186+ }
187+ mapping , found := isPathAvailableOnMachine (mounts , vmType , options .ContextDirectory )
188+ if ! found {
189+ logrus .Debugf ("Path %s is not available on the running machine" , options .ContextDirectory )
190+ return nil , options , false
191+ }
192+ options .ContextDirectory = mapping .RemotePath
193+
194+ // Containerfiles
195+ translatedContainerFiles := []string {}
196+ for _ , containerFile := range containerFiles {
197+ if strings .HasPrefix (containerFile , "http://" ) || strings .HasPrefix (containerFile , "https://" ) {
198+ translatedContainerFiles = append (translatedContainerFiles , containerFile )
199+ continue
200+ }
201+
202+ // If Containerfile does not exist, assume it is in context directory
203+ if err := fileutils .Lexists (containerFile ); err != nil {
204+ if ! errors .Is (err , fs .ErrNotExist ) {
205+ logrus .Fatalf ("Failed to check if containerfile %s exists: %v" , containerFile , err )
206+ return nil , options , false
207+ }
208+ continue
209+ }
210+
211+ mapping , found := isPathAvailableOnMachine (mounts , vmType , containerFile )
212+ if ! found {
213+ logrus .Debugf ("Path %s is not available on the running machine" , containerFile )
214+ return nil , options , false
215+ }
216+ translatedContainerFiles = append (translatedContainerFiles , mapping .RemotePath )
217+ }
218+
219+ // Additional build contexts
220+ for _ , context := range options .AdditionalBuildContexts {
221+ switch {
222+ case context .IsImage , context .IsURL :
223+ continue
224+ default :
225+ if err := fileutils .Lexists (context .Value ); errors .Is (err , fs .ErrNotExist ) {
226+ logrus .Debugf ("Path %s does not exist locally, skipping machine check" , context .Value )
227+ return nil , options , false
228+ }
229+ mapping , found := isPathAvailableOnMachine (mounts , vmType , context .Value )
230+ if ! found {
231+ logrus .Debugf ("Path %s is not available on the running machine" , context .Value )
232+ return nil , options , false
233+ }
234+ context .Value = mapping .RemotePath
235+ }
236+ }
237+ return translatedContainerFiles , options , true
238+ }
239+
240+ // IsHyperVProvider checks if the current machine provider is Hyper-V.
241+ // It returns true if the provider is Hyper-V, false otherwise, or an error if the check fails.
242+ func IsHyperVProvider (ctx context.Context ) (bool , error ) {
243+ conn , err := bindings .GetClient (ctx )
244+ if err != nil {
245+ logrus .Debugf ("Failed to get client connection: %v" , err )
246+ return false , err
247+ }
248+
249+ _ , vmProvider , err := FindMachineByPort (conn .URI .String (), conn .URI )
250+ if err != nil {
251+ logrus .Debugf ("Failed to get machine hypervisor type: %v" , err )
252+ return false , err
253+ }
254+
255+ return vmProvider .VMType () == define .HyperVVirt , nil
256+ }
257+
258+ // ValidatePathForLocalAPI checks if the provided path satisfies requirements for local API usage.
259+ // It returns an error if the path is not absolute or does not exist on the filesystem.
260+ func ValidatePathForLocalAPI (path string ) error {
261+ if ! filepath .IsAbs (path ) {
262+ return fmt .Errorf ("path %q is not absolute" , path )
263+ }
264+
265+ if err := fileutils .Exists (path ); err != nil {
266+ return err
267+ }
268+ return nil
269+ }
0 commit comments